Reputation: 2952
I'm trying to merge a char*-array into a uint16_t
. This is my code so far:
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;
I was expecting merged
to be 0xBE
, or in binary 00000000 10111110
.
But the output of the application is:
65470 As Bitset: 1111111110111110
In the following descriptions I'm reading bits from left to right.
So arr[1]
is at the right position, which is the last 8 bits.
The first 8 bits however are set to 1
, which they should not be.
Also, if I change the values to
arr[0] = 0x1; // Binary: 00000001
arr[1] = 0xBE; // Binary: 10111110
The output is:
0000000010111110
Again, arr[1]
is at the right position. But now the first 8 bits are 0
, whereas the last on of the first 8 should be 1
.
Basically what I wan't to do is append arr[1]
to arr[0]
and interpret the new number as whole.
Upvotes: 0
Views: 285
Reputation: 32576
Perhaps char
is signed type in your case, and you are left-shifting 0xBE
vhich is interpreted as signed negative value (-66
in a likely case of two's complement).
It is undefined behavior according to the standard. In practice it is often results in extending the sign bit, hence leading ones.
3.9.1 Fundamental types
....It is implementationdefined whether a char object can hold negative values.
5.8 Shift operators
....The value of
E1 << E2
isE1
left-shiftedE2
bit positions; vacated bits are zero-filled. IfE1
has an unsigned type, the value of the result isE1 × 2
E2
, reduced modulo one more than the maximum value representable in the result type. Otherwise, ifE1
has a signed type and non-negative value, andE1×2
E2
is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.
Upvotes: 1
Reputation: 385144
You need to assign to the wider type before shifting, otherwise you're shifting away† your high bits before they ever even hit the only variable here that's big enough to hold them.
uint16_t merged = arr[0];
merged <<= 8;
merged += arr[1];
Or, arguably:
const uint16_t merged = ((uint16_t)arr[0] << 8) + arr[1];
You also may want to consider converting through unsigned char
first to avoid oddities with the high bit set. Try out a few different values in your unit test suite and see what happens.
† Well, your program has undefined behaviour from this out-of-range shift, so who knows what might happen!
Upvotes: 1