我正在从这样的微控制器设备中读取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
指针访问缓冲区并直接读取值,但我必须做一些奇怪的bitmasking:
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
。
有人可以告诉我我的代码有什么问题吗?提前谢谢!
答案 0 :(得分:7)
您的问题是您的平台上已签署char
。因此,如果设置了buffer[11]
的高位,它将是一个负值,当你在表达式中使用它时,它将首先被提升为(负)整数,有效地传播{{1}的高位。 1}}进入所有更高位的位置。
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
可能更容易。