char byte = 0xff;
printf("%lu\n", sizeof(byte)) // Output is '1'
printf("%x\n", byte); // Output is 'ffffffff'
If the size of byte
is only one byte, then why does printf()
behave as if it is four bytes?
char byte = 0xff;
printf("%lu\n", sizeof(byte)) // Output is '1'
printf("%x\n", byte); // Output is 'ffffffff'
If the size of byte
is only one byte, then why does printf()
behave as if it is four bytes?
Formally, your program exhibits undefined behavior: %x
format specification expects an argument of type unsigned int
, but you are passing an int
, as explained below (hat tip @R). This is harmless in practice on modern two's-complement machines, since int and unsigned have compatible bit layouts. But again, technically, this is undefined behavior and it would be a good idea to fix it, as in printf("%x\n", (unsigned)byte);
.
The rules for passing parameters to variadic functions state that all integral types smaller than int get promoted to int. Otherwise, how would printf
know, upon seeing %x
, whether to grab one byte or four bytes off the stack? From the standard:
5.2.2p7 :
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg(18.10)...
If the argument has integral or enumeration type that is subject to the integral promotions(4.5),
or a floating point type that is subject to the floating point promotion(4.6),
the value of the argument is converted to the promoted type before the call.
This is how your char
turns into an int
. It's unspecified whether char
is signed or unsigned, but apparently, on the platform you use it's a signed type. So it gets sign-extended when promoted to int
. 0xff
is (char)-1
, and 0xffffffff
is (int)-1
.
I think it's due to integer promotion
A good blog post on this concept: http://www.idryman.org/blog/2012/11/21/integer-promotion/
You have invoked Undefined Behavior by passing the wrong argument type to printf
. The %x
specifier requires an argument of type unsigned int
, but you passed (due to default promotions) a signed int
. This is arguably valid if the value of the signed int
argument is non-negative, but on your system, plain char
happens to be a signed type, so byte
contains the result of applying an implementation-defined conversion to 0xff
; the usual result of this conversion is -1.
A char
is signed 8-bit. The "%x\n"
format says to print an integer. So the value of byte
is sign extended to an integer. Since a char
of 0xff
is, in that context, an 8-bit value of -1
, printf
is just printing the hex integer value of a -1
, which is ffffffff
.