我试图将char * -array合并到uint16_t
中。到目前为止,这是我的代码:
char* arr = new char[2]{0};
arr[0] = 0x0; // Binary: 00000000
arr[1] = 0xBE; // Binary: 10111110
uint16_t merged = (arr[0] << 8) + arr[1];
cout << merged << " As Bitset: " << bitset<16>(merged) << endl;
我希望merged
为0xBE
,或者为二进制00000000 10111110
。
但是应用程序的输出是:
65470 As Bitset: 1111111110111110
在以下说明中,我从左到右读取位。
所以arr[1]
位于正确的位置,即最后8位。
然而,前8位设置为1
,它们不应该是arr[0] = 0x1; // Binary: 00000001
arr[1] = 0xBE; // Binary: 10111110
。
另外,如果我将值更改为
0000000010111110
输出结果为:
arr[1]
同样,0
处于正确的位置。但现在前8位是1
,而前8位的最后一位应该是arr[1]
。
基本上我要做的就是将arr[0]
追加到{{1}}并将新号码解释为整体。
答案 0 :(得分:1)
在您的情况下,char
可能是签名类型,而且左移0xBE
vhich被解释为带符号的负值(-66
可能是two's complement )。
根据标准,它是未定义的行为。在实践中,它通常会导致符号位扩展,因此导致符号位。
3.9.1基本类型
....
它是实现定义的 char对象是否可以保存负值。
5.8转换运算符
....
E1 << E2
的值为E1
左移E2
位位置;空位是零填充的。如果E1
有未签名的 类型,结果的值是E1 × 2
E2
,减去模数比最大值可表示的 在结果类型中。否则,如果E1
具有签名类型且非负值,则E1×2
E2
可表示 在结果类型的相应无符号类型中,那么转换为结果类型的值是 结果价值;否则,行为未定义。
答案 1 :(得分:1)
你需要在移位之前分配更广泛的类型,否则你会在你的高位之前移开†,然后它们才能在这里找到足够大的唯一变量抱着他们。
uint16_t merged = arr[0];
merged <<= 8;
merged += arr[1];
或者,可以说:
const uint16_t merged = ((uint16_t)arr[0] << 8) + arr[1];
您还可以考虑先通过unsigned char
进行转换,以避免设置高位的奇怪现象。在单元测试套件中尝试一些不同的值,看看会发生什么。
†那么,你的程序在这个超出范围的转变中有未定义的行为,所以谁知道会发生什么呢!