不是按位运算符会破坏无符号整数?

Mil*_*owe 2 c types bit-manipulation unsigned-integer

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

每当我有一个无符号整数并将其用作按位NOT运算符的操作数时,它将根据2的补数求值为负数。但是根据定义,我使用的是无符号整数,即不应该带有符号的数字

下面是我的沙盒代码。我目前正在使用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
}

Run Code Online (Sandbox Code Playgroud)

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

Eri*_*hil 5

在C语言中,当int表达式中使用小于的整数时,它将自动提升为int。因此,在~x时,uint8_t将自动转换为一个int,然后按位~被执行,并且然后将结果传递给printf作为int。因此,打印出来的是反转an的所有位的结果int,而不仅仅是反转a的位的结果uint8_t

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

printf("NOT(%d) == %d", x, (uint8_t) ~x);
Run Code Online (Sandbox Code Playgroud)

请注意,uint8_t执行转换后,该值会再次自动提升为int,因此无论哪种情况printf都会收到int。但是,转换uint8_t会将值减小为可以表示的值,这是将要打印的值。

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

printf("NOT(%d) == %d", x, ~x & 0xff);
Run Code Online (Sandbox Code Playgroud)

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

printf("NOT(%d) == %d", x, (uint8_t) ~ (unsigned) x);
Run Code Online (Sandbox Code Playgroud)