位移位不正确?

Bit shifting not shifting correctly?

我正在使用 Si Labs IDE 用 C 语言对 8051 进行编程。我目前有三个字节:address_byte3, address_byte2, and address_byte1。然后我将变量 address_sum 初始化为 unsigned long int 然后对其进行以下操作...

address_sum=(address_byte3<<16)+(address_byte2<<8)+(address_byte1);

如果 address_byte3, address_byte2, & address_byte10x92, 0x56, & 0x78,这个操作会让我相信加载到 address_sum 的值将分别是 0xXX925678。相反,我得到 0xXX005678 的值。我的逻辑似乎很合理,但我又是编写代码的人,所以我有偏见,可能会因自己的无知而蒙蔽双眼。有没有人知道为什么 address_byte 的值是 "lost"?

谢谢。

短于 int 的变量在对它们进行计算时被提升为 int。您的 int 类型似乎是 16 位的,因此将其移动 16 位不正确。

您应该将变量显式转换为结果类型 (unsigned long):

address_sum = ((unsigned long)address_byte3<<16) +
              ((unsigned long)address_byte2<<8) +
              (unsigned long)address_byte1;

最后一次施法是多余的,但不会造成伤害。

16 位 int/unsigned 的移位,正如 所解释的那样,只会产生 16 位的答案。

我避免转换,作为一般的推广方案,因为有时它可能会缩小结果,因为代码随着时间的推移而发展并且维护者使用更广泛的操作数。

备选方案:

((type_of_target) 1) *:这将确保每个操作 至少 目标的宽度。

unsigned long address_sum;
...
address_sum = (1UL*address_byte3<<16) + (1UL*address_byte2<<8) + address_byte1;

赋值到目的地再操作:

address_sum = address_byte3;
address_sum = address_sum << 8 + address_byte2;
address_sum = address_sum << 8 + address_byte1;

一个偷偷摸摸的,认为看起来不愉快的 1 行替代品。召回 * + 比 shift

更高的顺序优先级
address_sum = (0*address_sum + address_byte3 << 16) + 
              (0*address_sum + address_byte2 <<  8) + address_byte1;

考虑 问题并使用 8 位无符号 "bytes"。

我喜欢 chux 的变体

更大的申报地址; 字节声明 a,b,c;

address =a; address<<=8;
address|=b; address<<=8;
address|=c;

尽管到目前为止所有答案都是最冗长的,但应该优化为基本相同的代码。不过得测试具体的编译器才能看。无论如何,8051 能否在每条指令中一次移动多于一位?不记得了。