位掩码 (char)(0xFFFFFFB8 & 0xFF) 在C语言中不起作用。

3

我在处理位掩码或者说可能是处理了位溢出方面遇到了麻烦。

我从数据流中获取数据,它被存储在char类型的缓冲区中,而我需要访问缓冲区的特定索引。但是当我进行访问时,我得到了意外的结果。

就像下面这样:

char buffer[BUFFER_SIZE];

/* ...recv from network stream performed... */

printf("buffer[index] = 0x%x\n", buffer[index]); /* => 0xFFFFFFB8 */

char dummyChar = buffer[index] & 0x000000FF;
printf("dummyChar = 0x%x\n", dummyChar); /* => 0xFFFFFFB8 */

缓冲区是char类型。为什么我打印buffer[index]时得到32位大小?

我还将buffer[index]屏蔽为0x000000FF,但我仍然得到0xFFFFFFB8。为什么?

我只想得到0xB8,有人能告诉我怎么做吗?我非常确定它是1字节大小的。


使用 unsigned char 而不是裸的 char - user824425
谢谢。现在它可以工作了! :) - Park Chansung
1
最好在进行这种编程时,到处使用stdint.h类型。 - Lundin
如果你需要8位,使用uint8_tchar不能保证有8位(如果它确实有8位,那么uint8_t是由标准保证的)。 - too honest for this site
正如Olaf所写,您应该使用uin8_t,并使用printf("0x%"PRIx8"\n",buffer[index])来打印它(包括<inttypes.h>以使用它)。请参阅C99草案n1256:7.8.1。 - 12431234123412341234123
2个回答

4
有两个原因:第一个是当传递比int小的整数类型时,它会自动提升为int(这可能会扩展符号位)。第二个原因是因为printf格式"%x"用于打印unsigned int值,而不是字节。
对于无符号字节(unsigned char),您应该使用修饰符hh,如"%hhx"。然后printf将知道传递的值真正是单个无符号字节,而不是完整的unsigned int
请参见上面链接的参考文献以获取更多详细信息。

我尝试了你的建议,但它没有奏效。并且缓冲区的索引并不是全部都打印为0xFFFFFF。有些字节以正确的方式打印出来。当我将(buffer[index] & 0x000000FF)强制转换为(int)时,它给了我0xB8... - Park Chansung
1
你的链接说"%x"需要一个无符号整数,而不是一个整数。 - mch

2
您正在尝试掩盖的字符buffer[index]在您的计算机上的char类型是带符号的,因此它的值为-72。它的十六进制表示为0xB8。
当参数buffer[index]传递给printf函数时,将执行整数提升。这意味着其类型char被提升为int类型。在您的计算机上,类型int中-72的表示与类型char中-72的表示不同:
在char类型中,-72表示为0xB8。
在int类型中,-72表示为0xFFFFFFB8。
执行位与操作不会改变值:
char dummyChar = buffer[index] & 0x000000FF;

因为1:0xFF & 0xB8 == 0xB8。字符dummyChar的值将为-72。然后将dummyChar传递给printf调用,并发生与上述描述相同的提升过程。


1实际情况略有不同,因为位运算符也会进行整数提升,但结果是相同的。两种类型都被提升为int,然后执行按位与操作,然后将结果隐式转换为char:

0xFFFFFFB8 & 0x000000B8 == 0x000000B8
0x000000B8 == 0xB8

保留操作前的数值不变。

1
使用%x与负值是未定义的行为。 - M.M
那是有争议的。我认为我会同意,但这不是这个问题的主题。 - 2501
@M.M,不是的,这是完全定义好的行为。-72被转换为整数-72,而十六进制中的-720xFFFFFFB8 - Luis Colorado
@LuisColorado 你错了,标准明确规定%x必须提供一个unsigned int参数。这些评论不是进行深入讨论的地方。相关讨论请参见此处 - M.M
恐怕在男性区分有符号和无符号整数之前,%x就已经出现了。您引用的参考资料比%x格式的首次出现要新,不得不遵守旧的行为(不管是定义还是未定义)真是令人遗憾。 - Luis Colorado
显示剩余2条评论

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