为什么整型变量的值为'0xffffffff`>&燃气轮机;1 != 0x7fffff? int c=0xffffffff; printf(“%x\n”,(c)==(0xffffffff)); printf(“%x\n”,(c>>1)=(0xffffffff>>1));

为什么整型变量的值为'0xffffffff`>&燃气轮机;1 != 0x7fffff? int c=0xffffffff; printf(“%x\n”,(c)==(0xffffffff)); printf(“%x\n”,(c>>1)=(0xffffffff>>1));,c,C,第一个输出为1,但第二个输出为0。 和c>>1输出0xffffffff。但是为什么呢?整数常量0xffffffff的类型是无符号int。因此,当您对该值执行右移位时,值为0的位将从左移位 相反,c是一个int,包含一个负值。对负值执行右移是实现定义的,尽管大多数实现将通过从左移入值为1的位来保留符号 关于在比较正值和负值时打印1的原因: printf("%x\n", (c) == (0xffffffff)); 它与整数转换有关 当0xFFFFFF(无符号)被分配给c时,它

第一个输出为
1
,但第二个输出为
0

c>>1
输出
0xffffffff
。但是为什么呢?

整数常量
0xffffffff
的类型是
无符号int
。因此,当您对该值执行右移位时,值为0的位将从左移位

相反,
c
是一个
int
,包含一个负值。对负值执行右移是实现定义的,尽管大多数实现将通过从左移入值为1的位来保留符号


关于在比较正值和负值时打印1的原因:

printf("%x\n", (c) == (0xffffffff));
它与整数转换有关

当0xFFFFFF(无符号)被分配给
c
时,它将进行实现定义的转换,因为该值超出范围。在2的补码系统中,这通常意味着表示将直接应用于目的地。现在
c
的值为-1,表示为0xFFFFFF


现在进行比较。常量
0xffffffff
是无符号的,其值为232-1。将有符号值与大小相同的无符号值进行比较时,有符号值将转换为无符号值。这是通过将
无符号int
+1的最大值与有符号值相加以将其置于范围内实现的(根据标准)。因此,有符号值-1被转换为无符号值232-1。这是与0xFFFFFF相同的值,因此比较结果为真。

因为平台上的
0xFFFFFF
是类型为
unsigned int
的值。 因此
0xffffffff>>1
等于
0xffffffffU>>1
,即
0x7fffffffU

将类型为
unsigned int
的值赋给类型为
int
的变量时,该值将转换为目标类型
0xFFFFFF
即4294967295超出32位有符号整数的范围,因此自然无法按原样存储。但由于您的计算机使用两位补码系统,将保持不变,即所有位都将被设置,但值被解释为-1而不是4294967295

整数的右移行为在C标准中定义为实现。它作为算术右移,即使用符号扩展。因此,位表示
ffffffff
右移1将导致
ffffff
位表示;符号int表示值
-1

最后,当您使用
=
运算符将
int
无符号int
进行比较时,操作数将进行“常规算术转换”
int
-1将转换为
无符号int
,在两个补码系统上保留位模式,即
ffffffff
,但是现在该值将被解释为4294967295,而不是-1。但该值与0x7fffffff(2147483647)不相等,后者具有


更让人困惑的是
c
值不等于
0xffffffff
,即使相等运算符返回true也是如此!
c
的值将是-1,
0xffffffff
的值是
0xFFFFFFU
,即
4294967295
,显然
-1
4294967295
之间的区别是4294967296!但正是由于有符号/无符号的比较,
不同的值可以比较为相等的值,例如GCC将用
-Wextra
发出警告:

warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
    5 |   printf("%x\n", (c) == (0xffffffff));
      |                      ^~
[venv][vrcappsdev][master✗]                                                                                                                                                                      
要看到值确实是不同的,您需要将两侧强制转换为一个足够大的类型,以包含这两个值-
long-long-int
是一个可移植的类型:

printf("%d\n", (long long int)c == (long long int)0xffffffff);

不会打印1。

尝试打印
c>>1
0xffffffff>>1
int
无符号int
。我同意:试着打印这些值以更好地检查它。
c>>1
0xffffffff
0xffffffff>>1
0x7ffffffff
@HanwGeek然后你应该问that@HanwGeek你不同意它们不相等吗?
long-long-int
是可移植的吗?MSVC什么时候实现了
long-long-int
?我怀疑仍然有人在使用MSVC版本,但该版本没有将
long-long-int
作为标准类型。@EricPostFischil啊我在3小时前收到带外通知,但忘记修复:D