Language-lawyer perspective:
I believe that correct reference in C99/C11 standard is §6.3.1.3
(with emphasis mine):
- 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.
- 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.
- 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 */
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…