8051(8位)微控制器上出现意外的位移结果

时间:2012-04-10 14:32:21

标签: c embedded 8051 iar

请考虑以下代码:

#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年5月5日至2005年5月的草案),第6.5.7.3-4节。

  

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

     

E1的结果&lt;&lt; E2是E1左移E2位位置;空出的位   充满了零。如果E1具有无符号类型,则为结果的值   是E1×2 ^ E2,减去模数比可表示的最大值   结果类型。如果E1具有带符号类型和非负值,则   E1×2 ^ E2在结果类型中是可表示的,然后就是结果   值;否则,行为未定义。

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

我错过了什么吗?感谢。

2 个答案:

答案 0 :(得分:1)

我弄明白发生了什么。即使没有优化,我没有使用crc16的事实似乎改变了语义。如果我在最后添加以下行,

if (crc16) 
        crc16 = 0x1234;

然后crc16在crc16 = crc16&lt;&lt;之后具有期望值(0x4300)。 8;

答案 1 :(得分:1)

您也可以将crc16声明为易失性,正如Adam Casey评论的那样。