请参阅此代码段
int main()
{
unsigned int a = 1000;
int b = -1;
if (a>b) printf("A is BIG! %d\n", a-b);
else printf("a is SMALL! %d\n", a-b);
return 0;
}
这给出了输出:a是SMALL:1001
我不明白这里发生了什么。怎么>在这里工作?为什么“a”小于“b”?如果它确实更小,为什么我得到一个正数(1001)作为差异?
答案 0 :(得分:46)
不同整数类型之间的二进制操作在由所谓的通常的算术转换定义的“公共”类型中执行(参见语言规范,6.3.1.8)。在您的情况下,“常见”类型为unsigned int
。这意味着int
操作数(您的b
)将在比较之前转换为unsigned int
,以及执行减法。
当-1
转换为unsigned int
时,结果是最大可能的unsigned int
值(与UINT_MAX
相同)。毋庸置疑,它会比您的未签名1000
值更大,这意味着a > b
确实是假的,a
确实小与{{{ 1}}。代码中的(unsigned) b
应解析为if
分支,这是您在实验中观察到的内容。
相同的转换规则适用于减法。您的else
实际上被解释为a-b
,结果的类型为a - (unsigned) b
。由于unsigned int
仅适用于已签名的值,因此无法使用%d
格式说明符打印此类值。您尝试使用%d
打印它会导致未定义的行为,因此从C语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义。
编辑:实际上,我对未定义的行为部分可能是错误的。根据C语言规范,相应的有符号和无符号整数类型范围的公共部分应具有相同的表示(根据脚注31,“可互换性作为函数的参数”)。因此,%d
表达式的结果是如上所述的无符号a - b
,除非我遗漏了某些内容,否则使用1001
说明符打印此特定无符号值是合法的,因为它会丢失在%d
的正范围内。使用int
打印(unsigned) INT_MAX + 1
将是未定义的,但%d
没问题。
答案 1 :(得分:14)
在int
为32位的典型实现中,转换为unsigned int
时的-1为4,294,967,295,确实≥1000。
即使您在unsigned
世界中对待减法,1000 - (4,294,967,295) = -4,294,966,295 = 1,001
也是如此。
这就是为什么gcc
会在unsigned
与signed
进行比较时发出警告的原因。 (如果没有看到警告,请传递-Wsign-compare
标志。)
答案 2 :(得分:0)
您正在进行无符号比较,即比较1000到2 ^ 32 - 1。
由于printf中的%d,输出已签名。
N.B。有时混合有符号和无符号操作数时的行为是特定于编译器的。我认为最好避免它们,并在有疑问时进行演员表。
答案 3 :(得分:0)
找到一种简单的比较方法,当你无法摆脱无符号声明时可能很有用(例如,[NSArray count]),只需将“unsigned int”强制为“int”。
如果我错了,请纠正我。
if (((int)a)>b) {
....
}
答案 4 :(得分:0)
硬件旨在将已签名与已签名和无符号进行比较。
如果需要算术结果,请先将无符号值转换为更大的有符号类型。否则,编译器会假设比较实际上是在无符号值之间。
-1表示为1111..1111,因此它的数量非常大......最大的...当被解释为无符号时。
答案 5 :(得分:0)
#include<stdio.h>
int main()
{
int a = 1000;
signed int b = -1, c = -2;
printf("%d",(unsigned int)b);
printf("%d\n",(unsigned int)c);
printf("%d\n",(unsigned int)a);
if(1000>-1){
printf("\ntrue");
}
else
printf("\nfalse");
return 0;
}
为此,您需要了解运算符的优先级
关系运算符从左到右工作... 所以它来了
if(1000> -1)
然后首先它将-1更改为无符号整数,因为int默认情况下被视为无符号数字,并且其范围大于有符号数字
-1将变为无符号数字,它将变为非常大的数字
答案 6 :(得分:-1)
比较a> b(其中a为无符号int类型,b为int类型)时, b类型转换为unsigned int ,因此,有符号int值-1转换为unsigned MAX的最大值** (范围:0至(2 ^ 32)-1)** 因此,a> b,即(1000> 4294967296)变为假。因此,否则执行循环 printf(“ a is SMALL!%d \ n”,a-b); 。