我正在学习《C语言程序设计》(作者为K&R)。目前我正在学习位运算部分,但是我对以下代码理解困难。
int mask = ~0 >> n;
我打算使用这个来掩盖另一个二进制数字的左侧,就像这样。 0000 1111 1010 0101 // 随机数
我的问题是,当我打印变量mask时,它仍为负数-1。假设n为4。我以为将~0(即-1)向左移动会得到15(0000 1111)。
感谢回答。
我正在学习《C语言程序设计》(作者为K&R)。目前我正在学习位运算部分,但是我对以下代码理解困难。
int mask = ~0 >> n;
我打算使用这个来掩盖另一个二进制数字的左侧,就像这样。 0000 1111 1010 0101 // 随机数
我的问题是,当我打印变量mask时,它仍为负数-1。假设n为4。我以为将~0(即-1)向左移动会得到15(0000 1111)。
感谢回答。
unsigned int mask = ~0u >> n;
将负数有符号整型右移是一种实现定义的行为,通常(但不总是)会用1填充左侧而不是0。这就是为什么无论您向右移动多少位,结果始终为-1,因为左侧始终由1填充。
当您移动无符号整数时,左侧始终会被0填充。所以您可以这样做:
unsigned int mask = ~0U >> n;
^
请注意,int
通常为2或4字节,这意味着如果您想获得15,您需要向右移动12或28位而不仅仅是4位。您可以使用char
代替:
unsigned char mask = ~0U;
mask >>= 4;
U
后缀表示它是一个无符号类型,在这种情况下特指 unsigned int
。 - Keith Thompsonint
且n==0
时,int mask = ~0U >> n;
会导致将一个超出范围的unsigned
赋值给int
,这样会产生更多的实现定义行为。使用无符号类型进行移位操作要简单得多。 - chux - Reinstate Monica>>
(通常) 用于对有符号变量(如int
)进行位移时是一种算术右移。这意味着从左侧移入的新位是前一个最高有效位(MSB)的副本。这具有保留二进制补码负数的符号(以及值)的效果。unsigned int
)时,会应用这种方法。在你的情况下,如果你计划在位级别上工作(即使用掩码等),我强烈建议做两件事:C和C ++中的>>运算符不一定是算术移位。仅当其在有符号整数类型的左侧使用时,它通常才是算术移位。如果它代替使用了无符号整数类型,则它将是一个逻辑移位。
<stdint.h>
的具有特定大小的类型,例如 uint32_t
。