Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
728 views
in Technique[技术] by (71.8m points)

casting - Typecasting int to char in printf() in C

int *int_pointer = malloc(10);

*int_pointer = 53200;

printf("The integer at byte #0 is set to: %d 
", (char) *int_pointer);

RESULT: -48

So I was just trying this out to see what would happen and I got this really unexpected result.

Why -48? How did it even turn into negative?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Language-lawyer perspective:

I believe that correct reference in C99/C11 standard is §6.3.1.3 (with emphasis mine):

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

Note that char type is problematic, since it's also implementation-defined if it's actually represented as signed or unsigned. The only way that is fully-defined by standard itself is cast to unsigned char type.

Practical view:

Assuming that for your implementation sizeof(int) == 4 and it uses two's complement method for storing signed integers, the number 53200 is represented as:

0000 0000 0000 0000 1100 1111 1101 0000

Note that if you have little-endian CPU (probably it's true assumption), then order of bytes, or more strictly how they are actually stored in memory and CPU registers is inverted,i.e. that number is stored as:

0000 1101 1111 1100 0000 0000 0000 0000

What (unsigned char) 53200 produces is result of (in purely mathematical sense) substraction as (note that standard guarantees that sizeof(unsigned char) == 1):

53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208

which is in binary 1101 0000

It can be mathematically proven that result is always the same as "cut-off", resting only last, least-significant byte as result of cast.

Note for printf():

As pointed by @pmg printf() is variadic function and due to default argument promotion its optional arguments of type unsigned char (or signed char and char as well) are always promoted to int, but this time it's "just a formality".

Note for alternative biwise operator solution:

As an alternative solution you can use biwise & and operator with proper mask to obtain least-significant byte of particular number, for example:

*int_number & 0xff   /* mask is 0000 0000 0000 0000 1111 1111 */

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...