I’m reading a buffer of type char from a microcontroller device like this:
char data_buffer[DATA_LEN];
FILE *aq_dev = fopen(argv[1], "r");
fread(data_buffer, 1, DATA_LEN, aq_dev);
fclose(aq_dev);
In this buffer blob there are unsigned 16bit integer numbers, each distributed over two entries in the buffer. For example there is
data_buffer[10] = 0x07
data_buffer[11] = 0xc3
which I would like to read out as 0x07c3 which equals 1987. Despite the fact that I originally thought I could just access the buffer with a uint16_t pointer and directly read the value, I have to do some strange bitmasking:
int value = (buffer[10] << 8) + buffer[11];
gives a wrong value beyond 35000 while a seemingly useless bitmasking like
int value = ((buffer[10] & 0xff) << 8) + (buffer[11] & 0xff);
returns the correct value.
How can an entry of an array of char be bigger than one byte?
According to my limits.h (Linux, x86_64) there is #define CHAR_BIT 8.
Can someone please tell me what is wrong with my code? Thanks in advance!
Your problem is that
charis signed on your platform. So if the high bit ofbuffer[11]is set, it will be a negative value, and when you use it in an expression it will first be promoted to a (negative) integer, effectively propagating the high bit of thecharinto all higher bit positions.The reason that
&-ing with0xffworks is that thecharvalue is promoted tointbefore the&operation is performed:The fix is to cast to
unsigned charbefore performing the bit manipulation:It’s probably easier just to make
bufferan array ofunsigned char.