4

考虑以下代码:

#include <hal_types.h>

int main() {

    uint16 crc16;         // hal_types.h: typedef unsigned short  uint16;

    crc16 = 0x43;         // debugger: crc16 == 0x0043, as expected
    crc16 = crc16 << 8;   // crc16 == 0x0000 ????

    return 0;
}

此代码在 TI CC1111 SoC(具有 8051 内核)上运行,并使用 IAR EW8051 8.10.3 编译/调试,配置为使用 C99 方言,未进行优化。评论中的值是使用 IAR 调试器观察到的(使用模拟器或实际设备的结果相同)。

我希望之后crc16 = crc16 << 8;crc16会有价值0x4300,而不是0x0000

根据 C99 标准(嗯,2005-05-06 年 5 月的草案),第 6.5.7.3-4 节。

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

E1 << E2 的结果是 E1 左移 E2 位位置;空出的位用零填充。如果 E1 具有无符号类型,则结果的值为 E1 × 2^E2,比结果类型中可表示的最大值多模一减少。如果 E1 具有带符号类型和非负值,并且 E1 × 2^E2 在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。

我对此的看法是,结果类型应该是一个无符号的 16 位整数,其值为((0x0043)*(2^8)) % 0x10000 == 0x4300.

我错过了什么吗?谢谢。

4

2 回答 2

1

You could also declare crc16 as volatile, as Adam Casey commented.

于 2013-10-07T17:06:59.380 回答
1

I figured out what's going on. Even though there's no optimization, the fact that I didn't use crc16 seems to have changed the semantics. If I add the following lines at the end,

if (crc16) 
        crc16 = 0x1234;

then crc16 has the expected value (0x4300) after crc16 = crc16 << 8;.

于 2012-04-10T15:20:05.100 回答