NOT(~) 带符号类型数的按位运算符

NOT(~) bitwise operator on signed type number

我不太理解 not(~) 运算符如何处理正符号数。

例如 -ve 数字存储在 2 的补码中

int a=-5; 
cout<<bitset<32>(a)<<endl;  // 11111111111111111111111111111011
cout<<bitset<32>(~a)<<endl; // 00000000000000000000000000000100
cout<<(~a)<<endl; // 4

4 是预期输出

但是

int a=5;
cout<<bitset<32>(a)<<endl;  // 00000000000000000000000000000101
cout<<bitset<32>(~a)<<endl; // 11111111111111111111111111111010
cout<<(~a)<<endl; // -6

怎么会是-6?

按位非(~)运算符基本上可以概括为如下

~x == -(x+1)

之所以这样,是因为否定(一元-)一般使用2's complement

二的补码定义为按位取非然后加一,即-x == (~x) + 1。将 + 1 简单转置到另一侧,然后使用负号的分配式 属性(即乘法的分配式 属性,在这种情况下具体为 -1),我们把等式放在上面。

在更数学的意义上:

-x == (~x) + 1  // Due to way negative numbers are stored in memory (in 2's complement)
-x - 1 == ~x    // Transposing the 1 to the other side
-(x+1) == ~x    // Distributing the negative sign

这是由于计算机如何理解带符号的数字。 取一个字节:8位。

1名(强者)设计

7为号码 作为一个整体: 所以从 -128 到 +127

对于负数: -128 到 -1

对于正数:0 到 127。

数字中不需要两个0,所以多了一个负数

C++ 标准仅说明二进制 NOT 运算符 (~) 翻转所有用于表示值的位。这对整数值意味着什么取决于您的机器使用的位的解释。 C++ 标准允许有符号整数的以下三种表示形式:

  • sign+magnitde:有一个符号位,后面是编码幅度的位。
  • 补充:想法是通过翻转x的所有位来表示-x。这类似于 sign+magnitude,在负的情况下,magnitude 位都被翻转。所以,1...1111 会是 -0,1...1110 会是 -1,1...1101 会是 -2 等等...
  • two's complement:此表示删除零的两种可能编码之一,并在下端添加一个新值。在二进制补码中,1...1111 表示-1,1...1110 表示-2,依此类推。所以,它基本上是一个比一个补码向下移动的。

如今,补码 更受欢迎。据我所知,X86、X64、ARM、MIPS 都将这种表示形式用于有符号数。您的机器显然也使用二进制补码,因为您观察到 ~5 为 -6。

如果你想保持 100% 的可移植性,你不应该依赖二进制的补码表示并且只在无符号类型上使用这些类型的运算符。