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

发布于 2024-08-18 09:07:46 字数 303 浏览 2 评论 0原文

请参阅此代码片段

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 is SMALL: 1001

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

百善笑为先 2024-08-25 09:07:46

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

-1 转换为 unsigned int 时,结果是最大可能的 unsigned int 值(与 UINT_MAX 相同) 。不用说,它将大于您的无符号 1000 值,这意味着 a > > b 确实是 false,并且与 (无符号)b 相比,a 确实。代码中的 if 应解析为 else 分支,这就是您在实验中观察到的情况。

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

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

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 int operand (your b) will get converted to unsigned int before the comparison, as well as for the purpose of performing subtraction.

When -1 is converted to unsigned int the result is the maximal possible unsigned int value (same as UINT_MAX). Needless to say, it is going to be greater than your unsigned 1000 value, meaning that a > b is indeed false and a is indeed small compared to (unsigned) b. The if in your code should resolve to else branch, which is what you observed in your experiment.

The same conversion rules apply to subtraction. Your a-b is really interpreted as a - (unsigned) b and the result has type unsigned int. Such value cannot be printed with %d format specifier, since %d only works with signed values. Your attempt to print it with %d results 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.

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 - b expression is unsigned 1001 as described above, and unless I'm missing something, it is legal to print this specific unsigned value with %d specifier, since it falls within the positive range of int. Printing (unsigned) INT_MAX + 1 with %d would be undefined, but 1001u is fine.

赠意 2024-08-25 09:07:46

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

即使您在 code>unsigned world,1000 - (4,294,967,295) = -4,294,966,295 = 1,001 这就是你得到的。

这就是为什么当您将 unsignedsigned 进行比较时,gcc 会发出警告。 (如果您没有看到警告,请传递 -Wsign-compare 标志。)

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

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

That's why gcc will spit a warning when you compare unsigned with signed. (If you don't see a warning, pass the -Wsign-compare flag.)

孤云独去闲 2024-08-25 09:07:46

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

由于 printf 中的 %d,输出是有符号的。

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

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

The output is signed because of %d in printf.

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.

浅笑依然 2024-08-25 09:07:46
 #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;
 }

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

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

    if(1000>-1)

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

-1 将更改为无符号数,它变成了一个非常大的数字

 #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)

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 will change into the unsigned number ,it changes into a very big number

笑叹一世浮沉 2024-08-25 09:07:46

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

如果我错了,请纠正我。

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

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".

Please correct me if I am wrong.

if (((int)a)>b) {
    ....
}
于我来说 2024-08-25 09:07:46

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

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

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

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.

つ可否回来 2024-08-25 09:07:46

在比较 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); 被执行。

while comparing a>b where a is unsigned int type and b is int type, b is type casted to unsigned int so, 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文