C语言 无符号和有符号整数的比较运算

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2084949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:10:55  来源:igfitidea点击:

Comparison operation on unsigned and signed integers

cgccunsignedsigned

提问by Gitmo

See this code snippet

看到这个代码片段

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;
}   

This gives the output: a is SMALL: 1001

这给出了输出:a is SMALL: 1001

I don't understand what's happening here. How does the > operator work here? Why is "a" smaller than "b"? If it is indeed smaller, why do i get a positive number (1001) as the difference?

我不明白这里发生了什么。> 运算符在这里如何工作?为什么“a”比“b”小?如果它确实更小,为什么我得到一个正数(1001)作为差异?

回答by AnT

Binary operations between different integral types are performed within a "common" type defined by so called usual arithmetic conversions(see the language specification, 6.3.1.8). In your case the "common" type is unsigned int. This means that intoperand (your b) will get converted to unsigned intbefore the comparison, as well as for the purpose of performing subtraction.

不同整数类型之间的二元运算在由所谓的普通算术转换定义的“公共”类型内执行(参见语言规范,6.3.1.8)。在您的情况下,“常见”类型是unsigned int. 这意味着int操作数(您的b)将unsigned int在比较之前转换为,以及用于执行减法。

When -1is converted to unsigned intthe result is the maximal possible unsigned intvalue (same as UINT_MAX). Needless to say, it is going to be greater than your unsigned 1000value, meaning that a > bis indeed false and ais indeed smallcompared to (unsigned) b. The ifin your code should resolve to elsebranch, which is what you observed in your experiment.

When-1转换为unsigned int结果是最大可能unsigned int值(与 相同UINT_MAX)。不用说,这将是比你更大的无符号的1000价值,也就是说,a > b的确是假的,a确实是(unsigned) b。在if你的代码应该下定决心else分支,这是你在实验中观察到的东西。

The same conversion rules apply to subtraction. Your a-bis really interpreted as a - (unsigned) band the result has type unsigned int. Such value cannot be printed with %dformat specifier, since %donly works with signedvalues. Your attempt to print it with %dresults in undefined behavior, so the value that you see printed (even though it has a logical deterministic explanation in practice) is completely meaningless from the point of view of C language.

相同的转换规则适用于减法。你a-b真的被解释为a - (unsigned) b并且结果有类型unsigned int。这样的值不能用%d格式说明符打印,因为%d只适用于带符号的值。您尝试打印它会%d导致未定义的行为,因此从 C 语言的角度来看,您看到打印的值(即使它在实践中具有逻辑确定性解释)完全没有意义。

Edit:Actually, I could be wrong about the undefined behavior part. According to C language specification, the common part of the range of the corresponding signed and unsigned integer type shall have identical representation (implying, according to the footnote 31, "interchangeability as arguments to functions"). So, the result of a - bexpression is unsigned 1001as described above, and unless I'm missing something, it is legal to print this specific unsigned value with %dspecifier, since it falls within the positive range of int. Printing (unsigned) INT_MAX + 1with %dwould be undefined, but 1001uis fine.

编辑:实际上,我可能对未定义行为部分有误。根据 C 语言规范,相应的有符号和无符号整数类型的范围的公共部分应具有相同的表示(根据脚注 31,“作为函数参数的可互换性”)。因此,a - b表达式的结果1001如上所述是无符号的,除非我遗漏了什么,否则使用%d说明符打印这个特定的无符号值是合法的,因为它落在int. 打印(unsigned) INT_MAX + 1with%d将是未定义的,但1001u很好。

回答by kennytm

On a typical implementation where intis 32-bit, -1 when converted to an unsigned intis 4,294,967,295 which is indeed ≥ 1000.

int32 位的典型实现中,-1 转换为 an 时unsigned int为 4,294,967,295,这确实≥ 1000。

Even if you treat the subtraction in an unsignedworld, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001which is what you get.

即使你在一个unsigned世界中对待减法,1000 - (4,294,967,295) = -4,294,966,295 = 1,001这就是你得到的。

That's why gccwill spit a warning when you compare unsignedwith signed. (If you don't see a warning, pass the -Wsign-compareflag.)

这就是为什么gcc当你unsignedsigned. (如果您没有看到警告,请传递-Wsign-compare标志。)

回答by harsh

 #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;
 }

For this you need to understand the precedence of operators

为此,您需要了解运算符的优先级

  1. Relational Operators works left to right ... so when it comes

    if(1000>-1)

  1. 关系运算符从左到右工作......所以当它出现时

    如果(1000>-1)

then first of all it will change -1 to unsigned integer because int is by default treated as unsigned number and it range it greater than the signed number

然后首先它会将 -1 更改为无符号整数,因为默认情况下 int 被视为无符号数,并且它的范围大于有符号数

-1 will change into the unsigned number ,it changes into a very big number

-1 会变成无符号数,变成一个很大的数

回答by Antti Huima

You are doing unsigned comparison, i.e. comparing 1000 to 2^32 - 1.

您正在进行无符号比较,即将 1000 与 2^32 - 1 进行比较。

The output is signed because of %d in printf.

由于 printf 中的 %d,输出被签名。

N.B. sometimes the behavior when you mix signed and unsigned operands is compiler-specific. I think it's best to avoid them and do casts when in doubt.

注意有时混合有符号和无符号操作数时的行为是特定于编译器的。我认为最好避免它们并在有疑问时进行转换。

回答by chenyi1976

Find a easy way to compare, maybe useful when you can not get rid of unsigned declaration, (for example, [NSArray count]), just force the "unsigned int" to an "int".

找到一种简单的比较方法,当您无法摆脱无符号声明时可能很有用(例如,[NSArray count]),只需将“unsigned int”强制为“int”即可。

Please correct me if I am wrong.

如果我错了,请纠正我。

if (((int)a)>b) {
    ....
}

回答by DigitalRoss

The hardware is designed to compare signed to signed and unsigned to unsigned.

硬件设计用于比较有符号与有符号以及无符号与无符号。

If you want the arithmetic result, convert the unsigned value to a larger signed type first. Otherwise the compiler wil assume that the comparison is really between unsigned values.

如果需要算术结果,请先将无符号值转换为更大的有符号类型。否则编译器将假定比较确实是在无符号值之间进行的。

And -1 is represented as 1111..1111, so it a very big quantity ... The biggest ... When interpreted as unsigned.

而 -1 表示为 1111..1111,所以它是一个非常大的数量......最大......当解释为无符号时。

回答by Naveen Kumar

while comparing a>b where a is unsigned int type and b is int type, b is type casted to unsigned intso, signed int value -1 is converted into MAX value of unsigned**(range: 0 to (2^32)-1 )** Thus, a>b i.e., (1000>4294967296) becomes false. Hence else loop printf("a is SMALL! %d\n", a-b);executed.

在比较 a>b 时,a 是 unsigned int 类型,b 是 int 类型,b 是类型转换为 unsigned int所以,signed int 值 -1 被转换为 unsigned 的 MAX 值**(范围:0 到(2^32) -1 )** 因此,a>b 即 (1000>4294967296) 变为假。因此 else 循环printf("a is SMALL! %d\n", ab); 执行。