让我们看一下为 32 位系统编译的以下代码:
typedef unsigned int uint32;
typedef unsigned char uint8;
...
uint8 y= 0xFF;
uint32 x = (y << 24U);
y可以提升为int as,我引用C标准:
If an int can represent all values of the original type, the value is converted to an int
根据相同标准,移位值有效:
The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
所以因为 y 提升为 int 并且移位值小于 int 的宽度 (24 < 32), there is no undefined behaviour.
但是,Misra 有一条规则 12.2,其中指出:
The right hand operand of a shift operator shall lie in the range zero
to one less than the width in bits of the essential type of the left hand
operand
注意规则文本中的 essential 关键字。这意味着 Misra 只查看 y 的基本类型,即 uint8,然后看到 24>=8(uint8 的宽度),因此将其视为违规。
为什么会出现这种差异?如果 C 编译器允许考虑提升,为什么 Misra 不允许?任何 C 编译器都会执行左操作数的提升,因此不会有编译器因未定义的行为而扰乱移位。
6.5.7p4:
如果 E1 具有有符号类型和非负值,并且
是 可以用结果类型表示,那么这就是结果值;否则,行为是未定义的。E1 × 2^E2
结果类型为 int,(假设典型的 32 位类型)无法表示 255 × 2^24 = 4278190080,因为它大于 2^31-1 = 2147483647。因此,行为未定义。