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 short
value 65,535 is automatically converted to anint
with the same value.1,2The
int
value 65,535 is passed toprintf
, which formats it as “65535” due to the%d
conversion specification.In
printf("unsigned int = %d\n", u_int);
, theunsigned int
value 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
%d
conversion specification,printf
seeks anint
value that was passed as an argument. For this, it finds the bits passed for yourunsigned int
, because anunsigned int
and anint
are passed in the same place in your C implementation, so theprintf
looking for anint
finds the bits in the same place the calling routine put theunsigned int
bits.3When interpreted as an
int
type, these bits, 32 ones, represent the value −1.3 Given the −1 value,printf
formats it as “-1” due to the%d
conversion 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.)