据我了解,当在 C 中将无符号整数右移多个位置时,左侧的空位置用零填充。
但是,我一直在尝试右移~0(这将是1111...1111(,但根本没有成功。尝试右移任意数量的位置都会产生相同的值,除非我在移位之前将整数存储在变量中:
#include <stdio.h>
int main() {
// Using an expression:
printf("%u n", ~0);
printf("%u n", ~0 >> 2);
unsigned int temp = ~0;
// Using a variable to store the value before shift:
printf("%u n", temp);
printf("%u n", temp >> 2);
return 0;
}
输出:
4294967295
4294967295
4294967295
1073741823
以任何一种方式执行左移 ~0 都完全没问题。我不确定这里发生了什么。
0
的类型是int
,而不是unsigned int
。因此,~0
是值为 0xffffffff
的int
(假设 32 位 int
s,看起来您有(。在大多数系统上,这意味着-1
,并且右移有符号整数将进行符号扩展(如果它开始为负,则保持负数(,再次给出0xffffffff
。
当你用%u
打印它时,printf
函数读取这个值-1
的有符号int
作为unsigned int
,并打印0xffffffff
对unsigned int
的意义。
请注意,所有这些只是大多数系统上大多数时间发生的情况。这具有多个未定义或实现定义的行为实例(负 int
s 的位模式、右移负 int
s 的作用,以及传入int
而不是unsigned int
时 %u
格式说明符的含义(。
~0U >> 2
这将确保它是未签名的。否则,您已签署操作。
整数文本始终为 int
类型(有符号int
(。现在,当您左移时,它是标志扩展的。
%u
期望未签名的int。您已向其传递已签名的 int。这是未定义的行为。
以下建议的代码更正了 OPs 代码并解决了问题的注释,包括删除未定义的行为。
#include <stdio.h>
int main( void )
{
// Using an expression:
printf("%u n", ~0U);
printf("%u n", ~0U >> 2);
unsigned int temp = ~0U;
// Using a variable to store the value before shift:
printf("%u n", temp);
printf("%u n", temp >> 2);
return 0;
}
输出为:
4294967295
1073741823
4294967295
1073741823