C 以下代码段的输出是什么?为什么? #包括 #包括 typedef无符号整数U32; int main(){ U32 var=-1; printf(“var=%u\n”,var); 如果(变量!=-1) { printf(“\n我不是-1\n”); } 其他的 { printf(“我是-1,变量:%u\n”,变量); } }

C 以下代码段的输出是什么?为什么? #包括 #包括 typedef无符号整数U32; int main(){ U32 var=-1; printf(“var=%u\n”,var); 如果(变量!=-1) { printf(“\n我不是-1\n”); } 其他的 { printf(“我是-1,变量:%u\n”,变量); } },c,implicit-conversion,arithmetic-expressions,C,Implicit Conversion,Arithmetic Expressions,此处“-1”应转换为无符号的int,并应分配给var。然后在条件下,如果条件,则不应等于-1。但是它进入了else语句。在这个语句中 #include <stdio.h> #include <stdlib.h> typedef unsigned int U32; int main() { U32 var = -1; printf("var = %u\n", var); if(var != -1) {

此处“-1”应转换为无符号的
int
,并应分配给
var
。然后在
条件下,如果
条件,则不应等于-1。但是它进入了
else
语句。

在这个语句中

#include <stdio.h>
#include <stdlib.h>
typedef    unsigned     int    U32;
int main() {
    U32 var     = -1;
    printf("var = %u\n", var);
    if(var != -1)
    {
        printf("\n I'm not -1\n");
    }
    else
    {
        printf("I'm -1 and Var :%u\n", var);
    }
 }
编译器需要确定操作数的公共类型。这个过程被称为通常的算术转换。 来自C标准(6.5.9相等运算符)

4如果两个操作数都有算术类型,则使用通常的算术类型 正在执行转换

与常用算术转换相关(C标准,6.3.1.8常用算术转换)

否则,如果具有无符号整数类型的操作数具有秩 大于或等于另一个操作数类型的秩,then 带符号整数类型的操作数转换为 无符号整数类型的操作数。

因此,根据if语句表达式中的引号,具有int类型的整型常量
-1
被转换为无符号int类型,即变量
var
的类型,因为int类型和无符号int类型具有相同的秩,而变量
var
具有无符号int类型


结果,该条件产生false。

一个
int
,无论是有符号还是无符号
,都由一系列位表示,如

B1B2…Bn

在哪里

毕∈ {0;1}

现在,最大的表示符号
unsigned
int
如下所示

if(var != -1)
但是,作为有符号值,-1表示为

1111...1


所以1111…1==1111…1是真的。转换为无符号
不会改变任何值,它会改变给定值的感知方式。在内存表示方面,2^(32-1)和-1实际上是同一个家伙,穿着不同的衣服。

请注意,所有整数常量,如
1
都有一个类型。假设
U32
unsigned int
,那么:

  • U32 var=-1的情况下(赋值),类型为
    int
    的右操作数转换为左操作数的类型

  • if(var!=-1)
    的情况下,
    -1
    操作数按照通常的算术转换从类型
    int
    转换为
    无符号int
    ,详情如下:

在这两种情况下,都会发生有符号到无符号的转换,并且这种转换根据6.3.1.3进行了明确定义:

否则,如果新类型是无符号的,则通过重复添加或 比新类型中可以表示的最大值多减去一个 直到值在新类型的范围内


这意味着在上述两种情况下,将生成相同的无符号值
0xffffff

为什么您认为第二个
-1
也不会被转换?编译器会警告您有符号/无符号比较不匹配?您还应该得到一个警告。但是它会继续进行,我不确定这有多重要,因为这里最重要的是如何进行整数转换。例如,
(long-long)-1==(unsigned long-long)-1
始终为真,但
(long-long)-1==(unsigned int)-1
始终为假。在其上加一个显式的
U
后缀可能会更清楚,并使编译器警告静音。@JL2210什么意思<代码>-1U
只会给你不同类型的警告。它会给你什么警告?@JL2210使用一元负号和无符号操作数等。编译器不需要为此发出警告,尽管我相信有些编译器会发出警告。静态分析仪肯定会这样做。无论如何,毫无疑问,带有无符号操作数的一元减号是非常可疑的代码。
1111...1