Search code examples
cbitwise-operatorsinteger-promotion

Truncating an int to char - is it defined?


unsigned char a, b;
b = something();
a = ~b;

A static analyzer complained of truncation in the last line, presumably because b is promoted to int before its bits are flipped and the result will be of type int.

I am only interested in the last byte of the promoted int - if b was 0x55, I need a to be 0xAA. My question is, does the C spec say anything about how the truncation happens, or is it implementation defined/undefined? Is it guaranteed that a will always get assigned the value I expect or could it go wrong on a conforming platform?

Of course, casting the result before assigning will silence the static analyzer, but I want to know if it is safe to ignore this warning in the first place.


Solution

  • The truncation happens as described in 6.3.1.3/2 of the C99 Standard

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


    Example for CHAR_BIT == 8, sizeof (unsigned char) == 1, sizeof (int) == 4

    So, 0x55 is converted to int, to 0x00000055, then negated to 0xFFFFFFAA, and

          0xFFFFFFAA
        + 0x00000100 /* UCHAR_MAX + 1 */
        ------------
          0xFFFFFEAA
    
        ... repeat lots and lots of times ...
    
          0x000000AA
    

    or, as plain 0xAA, as you'd expect