同时比较a> b,其中a是无符号int类型,b是int类型, b is type casted to unsigned int so,signed int value -1转换为无符号**的MAX值(范围:0到(2 ^ 32)-1)**因此,a> b ie,(1000> 4294967296)变为假 . 因此,执行了循环 printf("a is SMALL! %d\n", a-b); .
#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;
}
不同整数类型之间的二进制操作在由所谓的通常算术转换定义的"common"类型内执行(参见语言规范,6.3.1.8) . 在您的情况下,"common"类型是 unsigned int . 这意味着 int 操作数(您的 b )将在比较之前转换为 unsigned int ,以及执行减法的目的 .
当 -1 转换为 unsigned int 时,结果是最大可能的 unsigned int 值(与 UINT_MAX 相同) . 不用说,它会比你的无符号 1000 值更大,这意味着 a > b 确实是假的, a 确实比 (unsigned) b 小 . 代码中的 if 应解析为 else branch,这是您在实验中观察到的 .
相同的转换规则适用于减法 . 您的 a-b 实际上被解释为 a - (unsigned) b ,结果类型为 unsigned int . 无法使用 %d 格式说明符打印此值,因为 %d 仅适用于有符号值 . 您尝试使用 %d 打印它会导致未定义的行为,因此从C语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义 .
Edit: 实际上,我对未定义的行为部分可能是错的 . 根据C语言规范,相应的有符号和无符号整数类型范围的公共部分应具有相同的表示(暗示,根据脚注31,"interchangeability as arguments to functions") . 因此,如上所述, a - b 表达式的结果是无符号 1001 ,除非我遗漏了某些内容,否则使用 %d 说明符打印此特定无符号值是合法的,因为它落在 int 的正范围内 . 使用 %d 打印 (unsigned) INT_MAX + 1 将是未定义的,但 1001u 很好 .
0
在 int 为32位的典型实现中,转换为 unsigned int 时的-1为4,294,967,295,其确实≥1000 .
7 回答
硬件旨在将签名与签名和无符号进行比较 .
如果需要算术结果,请先将无符号值转换为更大的有符号类型 . 否则编译器将假设比较实际上是无符号值之间的比较 .
并且-1表示为1111..1111,因此它的数量非常大......最大...当被解释为无符号时 .
同时比较a> b,其中a是无符号int类型,b是int类型, b is type casted to unsigned int so,signed int value -1转换为无符号**的MAX值(范围:0到(2 ^ 32)-1)**因此,a> b ie,(1000> 4294967296)变为假 . 因此,执行了循环 printf("a is SMALL! %d\n", a-b); .
您正在进行无符号比较,即比较1000到2 ^ 32 - 1 .
由于printf中的%d,输出已签名 .
注:有时混合有符号和无符号操作数时的行为是特定于编译器的 . 我认为最好避免它们,并在有疑问时进行演员表演 .
为此,您需要了解运算符的优先级
如果(1000> -1)
然后首先它会将-1更改为无符号整数,因为int默认被视为无符号数,并且它的范围大于有符号数
-1将变为无符号数,它变为非常大的数字
找到一种简单的比较方法,当你无法摆脱无符号声明时(例如,[NSArray count]),只需将“unsigned int”强制为“int”即可 .
如果我错了,请纠正我 .
不同整数类型之间的二进制操作在由所谓的通常算术转换定义的"common"类型内执行(参见语言规范,6.3.1.8) . 在您的情况下,"common"类型是
unsigned int
. 这意味着int
操作数(您的b
)将在比较之前转换为unsigned int
,以及执行减法的目的 .当
-1
转换为unsigned int
时,结果是最大可能的unsigned int
值(与UINT_MAX
相同) . 不用说,它会比你的无符号1000
值更大,这意味着a > b
确实是假的,a
确实比(unsigned) b
小 . 代码中的if
应解析为else
branch,这是您在实验中观察到的 .相同的转换规则适用于减法 . 您的
a-b
实际上被解释为a - (unsigned) b
,结果类型为unsigned int
. 无法使用%d
格式说明符打印此值,因为%d
仅适用于有符号值 . 您尝试使用%d
打印它会导致未定义的行为,因此从C语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义 .Edit: 实际上,我对未定义的行为部分可能是错的 . 根据C语言规范,相应的有符号和无符号整数类型范围的公共部分应具有相同的表示(暗示,根据脚注31,"interchangeability as arguments to functions") . 因此,如上所述,
a - b
表达式的结果是无符号1001
,除非我遗漏了某些内容,否则使用%d
说明符打印此特定无符号值是合法的,因为它落在int
的正范围内 . 使用%d
打印(unsigned) INT_MAX + 1
将是未定义的,但1001u
很好 .在
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
标志 . )