I think the title explains pretty well what I'm asking so here is my code.
#include <stdio.h>
unsigned short u_short = 0xffff;
unsigned int u_int = 0xffffffff;
int main(){
printf("unsigned short = %d\n", u_short);
printf("unsigned int = %d\n", u_int);
return 0;
}
Here is my printout. printout picture
CodePudding user response:
printf("unsigned int = %d\n", u_int); is undefined behavior (UB) when u_int is out of the positive int range. Do not used "%d" to print unsigned.
Use printf("unsigned int = %u\n", u_int);
CodePudding user response:
This is likely what happened in your C implementation:
In
printf("unsigned short = %d\n", u_short);, theunsigned shortvalue 65,535 is automatically converted to anintwith the same value.1,2The
intvalue 65,535 is passed toprintf, which formats it as “65535” due to the%dconversion specification.In
printf("unsigned int = %d\n", u_int);, theunsigned intvalue 4,294,967,295 is passed toprintf; it is not converted to anint. As anunsigned int, 4,294,967,295 is represented with 32 one bits.Because of the
%dconversion specification,printfseeks anintvalue that was passed as an argument. For this, it finds the bits passed for yourunsigned int, because anunsigned intand anintare passed in the same place in your C implementation, so theprintflooking for anintfinds the bits in the same place the calling routine put theunsigned intbits.3When interpreted as an
inttype, these bits, 32 ones, represent the value −1.3 Given the −1 value,printfformats it as “-1” due to the%dconversion specification.
Footnotes
1 In many places in expressions, including arguments corresponding to ... of a function declaration, values of types narrower than int are automatically promoted to int, as part of the integer promotions.
2 A C implementation could have an unsigned short as wide as an int, in which case this conversion would not occur. That is rare these days.
3 This is a description of what likely happened in your C implementation. The behavior is not defined by the C standard and may vary in other C implementations or even in different programs in your C implementation.
CodePudding user response:
printf has some anomalies due to the usual argument promotions. In particular, arguments of type char and short are promoted to int when passing them to printf. Usually this is fine, but sometimes it results in surprises like these. What you get when you promote an unsigned 16-bit 0xffff to 32 bits is not 0xffffffff.
printf has some relatively little-known and relatively rarely-used modifiers to, in effect, undo those promotions and print char and short arguments as what they "really were". So you'll see more-consistent results if you tell printf that you were actually passing a short, like this:
printf("unsigned short = %hd\n", u_short);
printf("unsigned int = %d\n", u_int);
Now printf knows that the argument in the first call was really a short, so it treats it as such. On my machine, this now prints
unsigned short = -1
unsigned int = -1
(Now, with that said, it's arguably a bad idea to print unsigned integers with %d, as the other answers and comments have explained.)
