位移不正确移位?

时间:2017-04-12 18:25:01

标签: c long-integer bit-shift unsigned 8051

我使用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_sum如果address_byte3, address_byte2, & address_byte1分别为0x92, 0x56, & 0x78,那么加载到0xXX925678的值将为0xXX005678。相反,我的值为address_byte。我的逻辑看似合理,但我又是那个写代码的人,所以我有偏见,可能被我自己的无知蒙蔽了。有没有人有一个解决方案或解释为什么array[0][] = {5,B,2} array[1][] = {9,R,4} array[2][] = {3,B,1} array[3][] = {1,R,8} 的值是&#34;丢失&#34;?

谢谢。

3 个答案:

答案 0 :(得分:1)

int进行计算时,短于int的变量会提升为int。您的unsigned long类型似乎是16位,因此将其移位16位并不能正常工作。

您应该将变量显式地转换为结果类型(address_sum = ((unsigned long)address_byte3<<16) + ((unsigned long)address_byte2<<8) + (unsigned long)address_byte1; ):

.equal-height

最后一次铸造是多余的,但不会受到伤害。

答案 1 :(得分:1)

@anatolyg解释的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;
一个鬼鬼祟祟,以为不太令人愉快的单线替代方案。召回* +更高阶优先级而不是转移

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

考虑@Eugene Sh.关注并使用8位无符号&#34;字节&#34;。

答案 2 :(得分:0)

我的偏好是chux的变体

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

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

尽管到目前为止所有答案都是最详细的,但应该优化成基本相同的代码。但是必须要测试具体的编译器才能看到。无论如何,8051每次指令一次可以移位多于一位吗?别记得了。