Use Alexey Frunze's method for clarity, but here's a version with no tests (which may compile to faster inline code in some situations). This pattern works for other sizes of unsigned bit patterns as well—for instance, to handle 12-bit integers, use 0x0800
, for 17-bit integers use 0x10000
, and so on.
I bundled it with a little driver main
to show the outputs.
#include <stdio.h>
int comb(unsigned char msb, unsigned char lsb) {
long t = ((long)msb << 8) | lsb;
if (t >= 32768)
t -= 65536;
return t;
}
int comb2(unsigned char msb, unsigned char lsb) {
unsigned long t = ((unsigned long)msb << 8) | lsb;
t ^= 0x8000UL;
return (int)((long)t - (long)0x8000);
}
int main(void) {
printf("%6s %6s\n", "comb", "comb2");
printf("%6d %6d\n", comb(0, 0), comb2(0, 0));
printf("%6d %6d\n", comb(127, 255), comb2(127, 255));
printf("%6d %6d\n", comb(128, 0), comb2(128, 0));
printf("%6d %6d\n", comb(255, 255), comb2(255, 255));
return 0;
}