【问题标题】:bit masking (char)(0xFFFFFFB8 & 0xFF) doesn't work in c位掩码 (char)(0xFFFFFFB8 & 0xFF) 在 c 中不起作用
【发布时间】:2016-09-27 08:33:58
【问题描述】:

我正在为位屏蔽或处理位溢出而苦苦挣扎。

我从数据流中获取数据,它存储在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 类型。为什么我在打印缓冲区[索引] 时得到 32 位大小?

我还用 0x000000FF 掩盖了 buffer[index],但我仍然得到 0xFFFFFFB8。为什么?

我只想得到 0xB8,谁能告诉我怎么做?我很确定它是 1 字节大小..

【问题讨论】:

  • 使用unsigned char 而不是纯char
  • 谢谢。现在可以了! :)
  • 更好的是,在进行这种编程时,在任何地方都使用 stdint.h 类型。
  • 如果需要 8 位,请使用 uint8_tchar 不保证有 8 位(如果有,uint8_t 由标准保证)
  • Olaf 已经写好了,你应该使用uin8_t,并使用printf("0x%"PRIx8"\n",buffer[index]) 来打印它(包括 来使用它)。参见 C99 草案 n1256:7.8.1

标签: c bit-manipulation


【解决方案1】:

有两个原因:第一个是当传递小于int 的整数类型时,它会自动提升为int(这可能对值进行符号扩展)。第二个原因是因为printf 格式"%x" 用于打印unsigned int 值,而不是字节。

对于 unsigned 字节 (unsigned char),您应该使用修饰符 hh,如 "%hhx"。然后printf 将知道传递的值实际上是单个无符号字节,而不是完整的unsigned int

有关详细信息,请参阅上面的链接参考。

【讨论】:

  • 我尝试了您的建议,但没有成功。并不是所有的缓冲区索引都打印 0xFFFFFF 的东西。一些字节以正确的方式打印。而且,当我投射 (int)(buffer[index] & 0x000000FF) 时,它给了我 0xB8...
  • 您的链接显示"%x" 需要unsigned int,而不是int
【解决方案2】:

您尝试屏蔽的字符buffer[index] 的负值为-72,因为char 类型是在您的机器上签名的。它的十六进制表示是 0xB8。

当参数buffer[index] 传递给 printf 函数时,对其执行整数提升。这意味着它的类型,即 char,被提升为 int 类型。 -72 在 int 类型中的表示不同于 -72 在 char 类型中的表示,在您的机器上:

在 char 类型中,-72 表示为 0xB8。

在int类型中,-72表示为0xFFFFFFB8

执行和位运算不会改变值:

char dummyChar = buffer[index] & 0x000000FF;

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


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

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

保持与操作前相同的值。

【讨论】:

  • %x 与负值一起使用是未定义的行为
  • 这值得商榷。我想我会同意,但这不是这个问题的主题。
  • @M.M,不,不是,它是完美定义的行为。 -72 转换为整数-72-72 十六进制是0xFFFFFFB8
  • @LuisColorado 你错了,标准明确规定%x 必须提供unsigned int 参数。这些 cmets 不是进行扩展讨论的地方。 See here相关讨论
  • 好吧,恐怕%x 在人们区分签名和未签名ints 的差异之前就已经出现在场景中了。您引用的引用比%x 格式的首次出现要新,很遗憾必须遵守旧的行为(无论是定义的还是未定义的)。
猜你喜欢
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
  • 2023-03-07
  • 2012-08-21
相关资源
最近更新 更多