【问题标题】:NOT bitwise operator breaks unsigned integers?不是按位运算符打破无符号整数?
【发布时间】:2019-08-05 23:28:32
【问题描述】:

我试图让 C 将倒转无符号整数解释为无符号整数。 如何在不将 C 解释为二进制补码的情况下反转无符号数的位?

每当我有一个无符号整数并将其用作按位非运算符的操作数时,它根据二进制补码计算为负数。但是根据定义我使用的是无符号整数,一个不应该有符号的数字

下面是我的沙盒代码。我目前使用的是 GCC 版本 9.1.1。

#include <stdio.h>
#include <stdint.h>

int main(){
   uint8_t x = 1;//0000 0001
   printf("NOT(%d) == %d", x, ~x);//1111 1110
}

我想要 254 (1111 1110) 的输出,但 C 将该值解释为二进制补码,所以我得到 -2。有没有办法让 C将倒置字节解释为二进制补码?

【问题讨论】:

  • 你告诉它把数字解释为用“%d”签名。使用“%u”。
  • 实际上这是未定义的行为,因为格式说明符与提供的类型不匹配,另外大小也不匹配......很可能,uint8_t 需要%hhu 格式说明符;更安全的是使用来自&lt;inttypes.h&gt; header 的适当宏。
  • @LeeDanielCrocker:这将打印 4294967294 或与unsigned int 宽度 (UINT_MAX-1) 相对应的类似值,而不是问题所寻求的 254。
  • @Aconcagua:格式说明符没有未定义的行为。整数提升自动将x 提升为int,因此参数x~x 都具有int 类型,这是使用%d 格式化的正确类型。

标签: c types bit-manipulation unsigned-integer


【解决方案1】:

在 C 中,当在表达式中使用比int 窄的整数时,它会自动提升为int。因此,在~x 中,uint8_t 会自动转换为int,然后按位执行~,然后将结果作为int 传递给printf。所以打印的是反转 int 的所有位的结果,而不仅仅是 uint8_t 的位。

要获得uint8_t 结果,请将表达式转换为uint8_t

printf("NOT(%d) == %d", x, (uint8_t) ~x);

请注意,在执行uint8_t 转换后,该值会再次自动提升为int,因此printf 在任何一种情况下都会收到int。但是,转换会将值减少为可在 uint8_t 中表示的值,这就是将要打印的值。

但是,到uint8_t 的转换使用int 作为源类型,因此~x 的位将根据实现的int 格式进行解释。要在不依赖 int 格式的情况下获取 ~x 的低位,可以使用 &amp; 0xff 提取它们,而不是使用强制转换:

printf("NOT(%d) == %d", x, ~x & 0xff);

或者,您可以对unsigned 值而不是int 值执行按位~

printf("NOT(%d) == %d", x, (uint8_t) ~ (unsigned) x);

【讨论】:

  • 这依赖于使用int 的2 补码的系统。例如,补码的结果会有所不同。你可以用(uint8_t)~(unsigned)x 来避免这种依赖
  • @chux 对 uint8_t 没有意义,因为它是 unsigned ,可以想象,系统可以为涉及该类型的任何操作提供 int8_t 一些跳跃。但是,是的,可能这样的系统永远不会存在。
  • @M.M 再次为真。
猜你喜欢
  • 1970-01-01
  • 2013-05-23
  • 2020-07-06
  • 1970-01-01
  • 2015-06-16
  • 2011-05-27
  • 1970-01-01
  • 2012-04-03
  • 2010-11-27
相关资源
最近更新 更多