C语言中的char类型是否大于一个字节?

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

请问有人能告诉我代码有什么问题吗?提前致谢!


1
char 是有符号的还是无符号的? - James McNellis
1个回答

6

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

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended
< p > 使用 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 数组。


好的,我理解你的观点,但是为什么位掩码会起作用呢?在移位之前对所有8位进行按位与操作不应该对值或特别是高位产生任何影响,对吗? - lynix
@lynix 在任何算术运算之前,包括 & 运算符在内,都会进行带符号扩展的整数转换。 - ecatmur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接