473,382 Members | 1,441 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

promotion of integer types


I have the following program. Under linux I've compiled it with gcc and in DOS
I've compiled it with TURBOC 2.01. I get different outputs when I run it.

/* start of program */
#include <stdio.h>

int main()
{
unsigned char u1=200, u2=200;
unsigned long l1 = 0;
unsigned int i = 0;

printf("u1 = %u and u2 = %u\n", u1, u2 );
printf("l1 = %lu\n", l1 );

l1 = u1 * u2;
i = u1 * u2;
printf("After multiplying the unsigned int result is:\n");
printf("i = %u\n", i );
printf("and the unsigned long result is:\n");
printf("l1 = %lu\n", l1 );

return 0;
}
/* end of program */

******** results with gcc ******************
u1 = 200 and u2 = 200
l1 = 0
After multiplying the unsigned int result is:
i = 40000
and the unsigned long result is:
l1 = 40000
********** results with turboc ****************
u1 = 200 and u2 = 200
l1 = 0
After multiplying the unsigned int result is:
i = 40000
and the unsigned long result is:
l1 = 4294941760

***************************

Now my questions:

Where are the TURBOC results coming from? It looks like that an
intermediate result is being stored as a signed integer type before
being promoted to an unsigned long. Is this permitted or is this a bug
or what?

Second: Is the gcc result correct? If I'm reading the standard correctly the product
of two unsigned chars will never overflow but will be given modulo 256. Shouldn't
my product be given as 40000(mod 256) = 64 and then promoted to unsigned long?

BTW, thanks to all who reponded to my previous question about array indices.

Steve

--
Nov 14 '05 #1
3 1948
sh********@ticnet.com wrote:
I have the following program. Under linux I've compiled it with gcc and in DOS
I've compiled it with TURBOC 2.01. I get different outputs when I run it.

/* start of program */
#include <stdio.h>

int main()
{
unsigned char u1=200, u2=200;
unsigned long l1 = 0;
unsigned int i = 0;

printf("u1 = %u and u2 = %u\n", u1, u2 );
I'd rather make this
printf("u1 = %u and u2 = %u\n", (unsigned int) u1,
(unsigned int) u2 );
printf("l1 = %lu\n", l1 );

l1 = u1 * u2; (int) u1 * (int) u2 gives us an overflow for 16-Bit ints,
thus undefined behaviour, leading here to
40000-2^16 = -25536
(unsigned long)-25536 = 2^32-25536 = 4294941760
i = u1 * u2;
(int) u1 * (int) u2 gives us an overflow for 16-Bit ints,
thus undefined behaviour, leading here to
40000-2^16 = -25536
(unsigned int)-25536 = 2^16-25536 = 40000

gcc probably uses 32-Bit ints.
Cheers
Michael
printf("After multiplying the unsigned int result is:\n");
printf("i = %u\n", i );
printf("and the unsigned long result is:\n");
printf("l1 = %lu\n", l1 );

return 0;
}
/* end of program */

[snip: the above output for turboc, the expected for gcc]
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #2
<sh********@ticnet.com> wrote in message
news:Pi**************************************@myp6 0.mysystem.org...
I have the following program. Under linux I've compiled it with gcc and
in DOS I've compiled it with TURBOC 2.01. I get different outputs when I
run it.

/* start of program */
#include <stdio.h>

int main()
{
unsigned char u1=200, u2=200;
unsigned long l1 = 0;
unsigned int i = 0; [snip] l1 = u1 * u2;
i = u1 * u2; [snip] return 0;
}
/* end of program */

******** results with gcc ******************
u1 = 200 and u2 = 200
l1 = 0
After multiplying the unsigned int result is:
i = 40000
and the unsigned long result is:
l1 = 40000

********** results with turboc ****************
u1 = 200 and u2 = 200
l1 = 0
After multiplying the unsigned int result is:
i = 40000
and the unsigned long result is:
l1 = 4294941760

***************************

Now my questions:

Where are the TURBOC results coming from? It looks like that an
intermediate result is being stored as a signed integer type before
being promoted to an unsigned long. Is this permitted or is this a bug
or what?
The standard says that objects or expressions of rank less than int (such as
unsigned char) are converted to int (if int can represent all values of the
original type) or unsigned int (otherwise); this is known as integer
promotion.
Second: Is the gcc result correct? If I'm reading the standard correctly
the product of two unsigned chars will never overflow but will be given
modulo 256.
You're reading correctly, but missing a bit: values of type unsigned char
are never multiplied, they are promoted first by the rule above. But it is
true that the product of two values of unsigned type will be reduced
according to the range of values for that type.
Shouldn't my product be given as 40000(mod 256) = 64 and then promoted to
unsigned long?


No, the unsigned char values are promoted (probably to int in both cases),
then the promoted values are multiplied (causing overflow for the 16-bit int
apparently used by Turbo C). Finally, for GCC (the standard doesn't say what
Turbo C must do), the int result is converted (not promoted) to unsigned
long.

With educated guesses of the ranges of the types in both compilers, the GCC
result is correct, and the program invokes undefined behaviour with Turbo C,
due to the overflow.

Alex
Nov 14 '05 #3

On Sat, 26 Mar 2005, Alex Fraser wrote:

The standard says that objects or expressions of rank less than int (such as
unsigned char) are converted to int (if int can represent all values of the
original type) or unsigned int (otherwise); this is known as integer
promotion.
...
You're reading correctly, but missing a bit: values of type unsigned char
are never multiplied, they are promoted first by the rule above.


That's what I needed to know. Thanks.

--

Nov 14 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: BigMan | last post by:
Can someone cite the rules for type promotion in C++? And, in particular, what is the type of the result of adding 2 values of type char?
4
by: Ray | last post by:
When a single-bit bitfield that was formed from an enum is promoted/cast into an integer, does ANSI C say anything about whether that integer should be signed or unsigned? SGI IRIX cc thinks it is...
112
by: Carsten Hansen | last post by:
Suppose I'm using an implementation where an int is 16 bits. In the program below, what function is called in the first case, and what is called in the second case? Also, if there is a difference...
16
by: TTroy | last post by:
Hello, I'm relatively new to C and have gone through more than 4 books on it. None mentioned anything about integral promotion, arithmetic conversion, value preserving and unsigned preserving. ...
5
by: Stef | last post by:
Hello I have been programming C now for a couple of months but at this moment I am a bit confused with types like double float etc.. My question wat type does the result have when a double...
21
by: Frederick Gotham | last post by:
I set about trying to find a portable way to set the value of UCHAR_MAX. At first, I thought the following would work: #define UCHAR_MAX ~( (unsigned char)0 ) However, it didn't work for me....
6
by: sarathy | last post by:
Hi, What is integer promotion? How is it different from arithmetic conversion? Regards, Sarathy
1
by: charles_gero | last post by:
Hi all, I had a question about the topics in the subject and posted to comp.std.c, but feel it may also be appropriate here. Please excuse this crosspost if it is in bad form. I have a...
2
by: Spoon | last post by:
Consider the following program: #include <stdint.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char **argv) { uint32_t a = strtoul(argv, 0, 0); uint32_t b = strtoul(argv, 0,...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.