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

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

我只对提升的 int 的最后一个字节感兴趣——如果b是 0x55,我需要a是 0xAA。我的问题是,C 规范是否说明了截断是如何发生的,还是实现定义/未定义?是否保证a将始终获得我期望的值,或者它会在符合标准的平台上出错?

当然,在分配之前强制转换结果会使静态分析器静音,但我想知道首先忽略这个警告是否安全。

4

5 回答 5

10

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

涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。

在这种情况下,如果您unsigned char是 8 位,则意味着结果将以 256 为模减少,这意味着如果b0x55a则确实会以0xAA.

但请注意,如果unsigned char大于8 位(这是完全合法的),您将得到不同的结果为确保您可以便携地获得0xAA结果,您可以使用:

a = ~b & 0xff;

(按位和应该在unsigned char8 位的平台上进行优化)。

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

于 2011-05-04T10:30:58.393 回答
6

截断发生如C99 标准的 6.3.1.3/2 中所述

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


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

因此,0x55​​ 转换为int, 为 0x00000055,然后取反为 0xFFFFFFAA,并且

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

    ...重复很多很多次...

      0x000000AA

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

于 2011-05-04T10:41:05.487 回答
1

它会按照您的意愿行事。铸造价值是安全的。

于 2011-05-04T10:23:40.967 回答
0

这个特定的代码示例是安全的。但是有理由警告不要随意使用 ~ 运算符。

这背后的原因是 ~ 在小整数变量上是更复杂表达式中的潜在错误,因为 C 中的隐式整数提升。想象一下,如果你有一个像这样的表达式

a = ~b >> 4;

它不会像预期的那样变为零。

如果您的静态分析器设置为包含 MISRA-C,例如,您将为每个 ~ 运算符收到此警告,因为 MISRA 强制将小整数类型上的任何操作的结果显式类型转换为预期类型,在这种情况下为 unsigned char .

于 2011-05-04T11:06:33.493 回答
0

让我们以 Win32 机器为例。
整数是 4 个字节,将其转换为 char 的结果就像删除了剩下的 3 个字节一样。

当您将 char 转换为 char 时,它被提升为什么并不重要。
~b will add 3 bytes at the left change 0s to 1 and then remove... It does not affect your one right byte.

相同的概念将适用于不同的架构(无论是 16 位还是 64 位机器)

假设它是小端的

于 2011-05-04T10:27:54.650 回答