将int截断为char - 是否已定义?

Ama*_*osh 5 c bitwise-operators integer-promotion

unsigned char a, b;
b = something();
a = ~b;
Run Code Online (Sandbox Code Playgroud)

静态分析器抱怨最后一行中的截断,可能是因为b在其位被翻转之前被提升为int并且结果将是int类型.

我只对提升的int的最后一个字节感兴趣 - 如果b是0x55,我需要a是0xAA.我的问题是,C规范是否说明截断发生的方式,还是实现定义/未定义?是否可以保证a总是会在合格的平台上分配我期望的值或者它可能出错?

当然,在分配之前投射结果会使静态分析器静音,但我想知道首先忽略此警告是否安全.

caf*_*caf 10

C标准为无符号类型指定了这个:

涉及无符号操作数的计算永远不会溢出,因为无法通过生成的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数量为模.

在这种情况下,如果你unsigned char是8位,这意味着结果将以模256减少,这意味着如果b0x55,a将确实最终为0xAA.

但需要注意的是,如果unsigned char超过8位(这是完全合法的),你会得到不同的结果.为了确保0xAA您可以轻松获得结果,您可以使用:

a = ~b & 0xff;
Run Code Online (Sandbox Code Playgroud)

(按位并且应该在unsigned char8位的平台上进行优化).

另请注意,如果使用带符号类型,则结果是实现定义的.


pmg*_*pmg 6

截断发生在C99标准的 6.3.1.3/2中

...如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.


CHAR_BIT == 8,sizeof(unsigned char)== 1,sizeof(int)== 4的示例

因此,0x55​​被转换为int0x00000055,然后被否定为0xFFFFFFAA,并且

      0xFFFFFFAA
    + 0x00000100 /* UCHAR_MAX + 1 */
    ------------
      0xFFFFFEAA

    ... repeat lots and lots of times ...

      0x000000AA

或者,正如0xAA您所期望的那样