简体   繁体   中英

Why does unsigned short (0xffff) print 65,535 and unsigned int (0xffffffff) print -1 in C?

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

This is likely what happened in your C implementation:

  • In printf("unsigned short = %d\n", u_short); , the unsigned short value 65,535 is automatically converted to an int with the same value. 1,2

  • The int value 65,535 is passed to printf , which formats it as “65535” due to the %d conversion specification.

  • In printf("unsigned int = %d\n", u_int); , the unsigned int value 4,294,967,295 is passed to printf ; it is not converted to an int . As an unsigned int , 4,294,967,295 is represented with 32 one bits.

  • Because of the %d conversion specification, printf seeks an int value that was passed as an argument. For this, it finds the bits passed for your unsigned int , because an unsigned int and an int are passed in the same place in your C implementation, so the printf looking for an int finds the bits in the same place the calling routine put the unsigned int bits. 3

  • When 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.

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);

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM