据我所知,当将无符号整数右移到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 :(得分:3)
~0U >> 2
这将确保它是未签名的。否则你就签了名。
积分文字始终为int
类型(已签名int
)。现在当你离开时,它会被标记延长。
%u
期望unsigned int。您已将一个signed int传递给它。这是未定义的行为。
答案 1 :(得分:3)
表达式0
的类型为int
,而非unsigned int
。因此,~0
是值为int
的 0xffffffff
(假设您看起来像32位int
)。在大多数系统上,这意味着-1
,右移有符号整数将进行符号扩展(如果它开始为负则保持为负),再次给予0xffffffff
。
当您使用%u
进行打印时,printf
函数会将带有int
的已签名-1
作为unsigned int
读取,并打印{{1} }}表示0xffffffff
。
请注意,所有这些都是大多数时间在大多数系统上发生的情况。这有多个未定义或实现定义行为的实例(负unsigned int
的位模式,右移负int
s,以及int
格式说明符通过时的含义在%u
而不是int
)。
答案 2 :(得分:0)
以下建议的代码更正OP代码并解决问题的注释,包括删除未定义的行为。
#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