Reading signed char using %u

為{幸葍}努か 提交于 2019-12-10 03:10:46

问题


#include <stdio.h>

int main() {
    int i,n;
    int a = 123456789;

    void *v = &a;

    unsigned char *c = (unsigned char*)v;

    for(i=0;i< sizeof a;i++) {
        printf("%u  ",*(c+i));
    }

    char *cc = (char*)v;
    printf("\n %d", *(cc+1));

    char *ccc = (char*)v;
    printf("\n %u \n", *(ccc+1));

}

This program generates the following output on my 32 bit Ubuntu machine.

21  205  91  7  
-51
4294967245

First two lines of output I can understand =>

  • 1st Line : sequence of storing of bytes in memory.
  • 2nd Line : signed value of the second byte value (2's complement).
  • 3rd Line : why such a large value ?

please explain the last line of output. WHY three bytes of 1's are added because (11111111111111111111111111001101) = 4294967245 .


回答1:


Apparently your compiler uses signed characters and it is a little endian, two's complement system.

123456789d = 075BCD15h
Little endian: 15 CD 5B 07

Thus v+1 gives value 0xCD. When this is stored in a signed char, you get -51 in signed decimal format.

When passed to printf, the character *(ccc+1) containing value -51 first gets implicitly type promoted to int, because variadic functions like printf has a rule stating that all small integer parameters will get promoted to int (the default argument promotions). During this promotion, the sign is preserved. You still have value -51, but for a 32 bit signed integer, this gives the value 0xFFFFFFCD.

And finally the %u specifier tells printf to treat this as an unsigned integer, so you end up with 4.29 bil something.

The important part to understand here is that %u has nothing to do with the actual type promotion, it just tells printf how to interpret the data after the promotion.




回答2:


-51 store in 8 bit hex is 0xCD. (Assuming 2s compliment binary system)

When you pass it to a variadic function like printf, default argument promotion takes place and char is promoted to int with representation 0xFFFFFFCD (for 4 byte int).

0xFFFFFFCD interpreted as int is -51 and interpreted as unsigned int is 4294967245.

Further reading: Default argument promotions in C function calls


please explain the last line of output. WHY three bytes of 1's are added

This is called sign extension. When a smaller signed number is assigned (converted) to larger number, its signed bit get's replicated to ensure it represents same number (for example in 1s and 2s compliment).


Bad printf format specifier
You are attempting to print a char with specifier "%u" which specifies unsigned [int]. Arguments which do not match the conversion specifier in printf is undefined behavior from 7.19.6.1 paragraph 9.

If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Use of char to store signed value
Also to ensure char contains signed value, explicitly use signed char as char may behave as signed char or unsigned char. (In latter case, output of your snippet may be 205 205). In gcc you can force char to behave as unsigned char with -funsigned-char option.



来源:https://stackoverflow.com/questions/36350405/reading-signed-char-using-u

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!