我正在从这样的微 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/