tomago is correct, your problem is caused by sign-extension.
At lines 6 and 7 you have what you expect:
a is 0, and
b is 0x8000.
However, if perchance your implementation uses two's-complement encoding for signed integers, then
b is considered to be a negative value.
Let's split line 10 into several lines so we can look at each term:
- uint32_t xa, xb;
-
...
-
xa = (uint32_t)a << 16;
-
xb = (uint32_t)b;
-
x = xa | xb;
Here
xa is 0, but
xb is 0xFFFF8000 because the sign bit is extended to the left.
By the way, are you sure the expression for
xa is correct? It is if the cast has a higher precedence than the shift-left. Does it? You don't need to remember the precedence table if you use parentheses.
You can solve the sign-extension issue if your computations are always performed on unsigned values.
- uint32_t x = 0x00008000uL;
-
uint16_t ua, ub;
-
int16_t = a, b;
-
-
//Split
-
ua = (uint16_t) (x >> 16);
-
ub = (uint16_t) (x & 0x0000FFFFuL);
-
a = (int16_t)ua;
-
b = (int16_t)ub;
-
-
//Reconstruction
-
ua = (uint16_t)a;
-
ub = (uint16_t)b;
-
x = (((uint32_t)ua) << 16) | ((uint32_t)ub);
Notice also the use of the
uL suffix.