我有这个程序:
#include <stdio.h>
int main(void)
{
unsigned char unit_id[] = { 0x2B, 0xC, 0x6B, 0x54}; // 8-bit (1 byte)
unsigned long long int unit_id_val; //64-bit (8 bytes)
int i;
// loops 4 times
for(i=0;i<sizeof(unit_id)/sizeof(char);i++){
unit_id_val |= unit_id[i] << (8 * i);
}
printf("the unit id is %llu\n", unit_id_val);
return 0;
}
十六进制到二进制转换:
0x2B = 00101011
0xC = 00001100
0x6B = 01101011
0x54 = 01010100
unit_id_val是8个字节(我在下面使用5个字节的unit_id_val来简化事情)
1)第一次迭代8 * 0 = 0因此不发生左移:
00101011 = 00101011 << 0
00000000 00000000 00000000 00000000 00000000 |= 00101011
所以结果应该是:
00000000 00000000 00000000 00000000 00101011
2)第二次迭代8 * 1 = 8,所以将无符号字符0xC的所有位左移8:
00000000 = 00101011 << 8
00000000 00000000 00000000 00000000 00101011 |= 00000000
所以结果应该是:
00000000 00000000 00000000 00000000 00101011
3)第三次迭代8 * 2 = 16,所以左移无符号字符0x6B的所有位16:
00000000 = 01101011 << 16
00000000 00000000 00000000 00000000 00101011 |= 00000000
所以结果应该是:
00000000 00000000 00000000 00000000 00101011
4)第四次迭代8 * 3 = 24,所以将无符号字符0x54的所有位左移32:
00000000 = 01010100 << 32
00000000 00000000 00000000 00000000 00101011 |= 00000000
所以结果应该是:
00000000 00000000 00000000 00000000 00101011
00101011是43
但是当你运行这个程序时,你得到了
1416301611
是二进制:
00010100 00010110 00110000 00010110 00010001
我不明白这里的意思。我通过在评估左移运算符&lt;&lt;之前评估主表达式operator()来遵循优先级图表。在评估赋值运算符之前!=。然而,我不明白为什么我得到了回应。
答案 0 :(得分:2)
00000000 = 00101011 << 8
好的,首先你的第二个元素是0x0C
(即二进制00001100
而不是00101011
),所以你实际上在做:
(unsigned char) 0x0C << 8
并且此表达式的结果不是0
而是0x0C00
,因为按位<<
运算符对其左操作数执行整数提升,因此它实际上等效于:
(int) (unsigned char) 0x0C << 8
答案 1 :(得分:1)
你永远不会初始化unit_id_val
,然后你|=
将你移位的字节值放入其中,所以在未初始化的值中设置的任何位仍然会被设置,所以你的输出看起来像随机的垃圾。添加
unit_id_val = 0;
在你的循环之前。
此外,每当您在C中执行任何操作时,操作数总是按标准转换进行转换。特别是,这意味着任何小于int
的整数类型将首先转换为int
。因此,即使unsigned char
仅为8位,当您执行unit_id[i] << (8 * i)
时,来自unit_id[i]
的8位值也将转换为int
(可能是您计算机上的32位)在转变之前。对于小于C中int
的整数,没有办法进行任何计算 - 即使你施放它们,它们也会被隐式转换回int
。< / p>
答案 2 :(得分:0)
请参阅此行
unit_id_val |= unit_id[i] << (8 * i);
unit_id_val = unit_id_val | unit_id[i] << (8 * i);
问题是你使用的是一个只声明但未初始化的变量,我们知道在未初始化的变量中,默认值是垃圾或垃圾。所以每次都毫无疑问地会得到一些不可预测的价值。