3

我正在char从这样的微控制器设备中读取类型的缓冲区:

char data_buffer[DATA_LEN];
FILE *aq_dev = fopen(argv[1], "r");

fread(data_buffer, 1, DATA_LEN, aq_dev);

fclose(aq_dev);

在这个缓冲区 blob 中有无符号的 16 位整数,每个整数分布在缓冲区中的两个条目上。例如有

data_buffer[10] = 0x07
data_buffer[11] = 0xc3

我想读出0x07c3它等于 1987。尽管我最初认为我可以用uint16_t指针访问缓冲区并直接读取值,但我必须做一些奇怪的位掩码:

int value = (buffer[10] << 8) + buffer[11];

给出超过 35000 的错误值,而看似无用的位掩码如

int value = ((buffer[10] & 0xff) << 8) + (buffer[11] & 0xff);

返回正确的值

数组的条目如何char大于一个字节? 根据我的limits.h(Linux, x86_64) 有#define CHAR_BIT 8.

有人可以告诉我我的代码有什么问题吗?提前致谢!

4

1 回答 1

6

您的问题是char在您的平台上签名。因此,如果buffer[11]设置了的高位,它将是一个负值,并且当您在表达式中使用它时,它将首先被提升为(负)整数,从而有效地将高位传播char到所有高位位置。

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended

&-ing with 0xffworks的原因是在执行操作之前将char值提升到:int&

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended
    & 0xff   (int)           0x000000c3 195

修复是unsigned char在执行位操作之前强制转换:

int value = (((unsigned char) buffer[10]) << 8) | ((unsigned char) buffer[11]);

buffer[11]   (char)                0xc3 -61
             (unsigned char)       0xc3 195
             (int)           0x000000c3 195

buffer制作一个数组可能更容易unsigned char

于 2012-10-11T17:29:31.877 回答