我正在从这样的微 Controller 设备读取 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

我想将其读出为等于 1987 的 0x07c3。尽管我最初认为我可以使用 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

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

最佳答案

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

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended
&0xff 一起工作的原因是 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 数组可能更容易。

关于C:字符大于一字节?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12845111/

10-11 22:39
查看更多