Integer promotion - what are the steps
Asked Answered
O

3

8

This code prints B2

short a=-5;
unsigned short b=-5u;
if(a==b)
    printf("A1");
else
    printf("B2");

I read about integer promotion but it's still unclear to me, how does it work in the example here? Can someone thoroughly post the steps the compiler follows in widening/truncating the values?

Oleviaolfaction answered 6/3, 2013 at 19:5 Comment(7)
which compiler are you using?Auster
this could be useful.Pinta
Integer promotion only happens in the a==b expression there - is that all you're asking about?Cosmopolitan
MSVC2012 but I'd like to know how a standard-following compiler would behaveOleviaolfaction
I'm not sure what you expected, it'll never be equal because unsigned short b = -5u will wrap around to 65531.Lechery
possible duplicate of unsigned becomes signed in if-statement comparisons?Osteophyte
See also Usual Arithmetic Conversions from Stephan T. Lavavej on Channel 9Lithoid
A
11

Let's walk through your code:

short a = -5;

a = -5, which fits into a short. So far so easy.

unsigned short b = -5u;

-5u means apply the unary - operator to the constant 5u. 5u is (unsigned int) 5, and the unary - does no promotion, so you end up with 4294967291 which is 2^32-5. (Update: I got this bit wrong in my original answer; see a test script which shows this version is correct here http://codepad.org/hjooaQFW)

Now when putting that in b, it is truncated to an unsigned short (2 bytes, usually), so b = 65531, which is 2^16-5.

if( a == b )

In this line, a and b are both promoted to ints so that the comparison can happen correctly. If they were promoted to shorts, b would potentially wrap around. If they were promoted to unsigned shorts, a would potentially wrap around.

So it's like saying if( (int) a == (int) b ). And a = -5, so (int) a = -5, and b = 65531, so (int) b = 65531, because ints are bigger than shorts.

Adest answered 6/3, 2013 at 19:15 Comment(8)
I wouldn't say -5u makes no sense - it is well-defined by the standard.Cosmopolitan
Um, -5u is perfectly sensible. It applies - to the integer constant 5u.Eohippus
You hit a point I'm interested in: so BEFORE -5 gets stored in the short 'a' variable... its constant value is treated as an integer, right? I'm deeply interested in this pointOleviaolfaction
@PeteBecker Updated the answer to account for that; it hadn't occurred to me. And Johnny, yes, it is an integer. Or you can use 5l to make it a long, or 5ul to make it an unsigned long, for example. Also note that a good compiler will complicate this hugely, but not in a way that it's possible to notice.Adest
@JohnnyPauling : -5 is converted to a signed int before it's assigned. It's then truncated to a short, but that's fine in this case.Tim
The unary - will not cause any conversion of the 5u. It will remain an unsigned int. Applying - to it will result in UINT_MAX - 4, then that is converted to unsigned short.Watermark
@EricPostpischil I was responding to Dave: "and the unary - will promote this (I presume to a long) with value -5."Watermark
@DanielFischer Seems you're right. I'm updating the answer again,Adest
S
2
a == b

a and b are both promoted to int in the above expression.

unsigned short b=-5u;

In this declaration -5U is converted to unsigned short by the means of integer conversion (C99, 6.3.1.3p2 applies here) and becomes a large value.

(C99, 6.3.1.3p2) "Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type."

b value is then (unsigned short) ((unsigned int) USHRT_MAX + 1 -5) which is (unsigned short) 65531 if USHRT_MAX is (unsigned short) 65535.

So what you have is:

(short) -5 == (unsigned short) 65531

which is equivalent after integer promotion of both operands to:

-5 == 65531

which is equivalent to 0.

Sublingual answered 6/3, 2013 at 19:9 Comment(2)
re "On a two's complement system", well it is that way regardless of signed integer representation, because the holy standard requires that it be binary, and because 5 is very much smaller then than the minimum required range, and because the standard requires unsigned arithmetic to be modulo 2^n where n is the number of representation bits. So for, say, 32-bit unsigned and 16-bit unsigned short the expression -5u in itself yields the value 2^32-5, and then that value modulo 2^16 is necessarily 2^16-5. again, regardless of signed integer representation.Hoof
@Cheersandhth.-Alf Agree, I removed this sentence just before your comment. I started with the on a two's complement system because I initially wanted to add information about the (no) representation change.Sublingual
A
1

short to unsigned short is a conversion (thus having conversion rank)

short to int is a promotion (thus having promotion rank)

Promotions are preferred over conversions because of the ranking. Promotions occur during arithmetic and other operations. Conversions occur when merely storing one integral type inside another. Arithmetic ops can cause conversions as well as promotions, in order to coerce the types together. For another example:

unsigned int u = 2; 
int i = 2; 
u + i;

i is converted (not promoted) to unsigned.

Your value is converted to a larger value because it wraps around due to being unsigned. Then, they are promoted to int. Thus a != b because of this.

Auster answered 6/3, 2013 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.