无符号和有符号整数的比较运算
请参阅此代码片段
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不同整数类型之间的二进制运算在由所谓的普通算术转换定义的“公共”类型内执行(请参阅语言规范,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 thatint
operand (yourb
) will get converted tounsigned int
before the comparison, as well as for the purpose of performing subtraction.When
-1
is converted tounsigned int
the result is the maximal possibleunsigned int
value (same asUINT_MAX
). Needless to say, it is going to be greater than your unsigned1000
value, meaning thata > b
is indeed false anda
is indeed small compared to(unsigned) b
. Theif
in your code should resolve toelse
branch, which is what you observed in your experiment.The same conversion rules apply to subtraction. Your
a-b
is really interpreted asa - (unsigned) b
and the result has typeunsigned 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 unsigned1001
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 ofint
. Printing(unsigned) INT_MAX + 1
with%d
would be undefined, but1001u
is fine.在
int
为 32 位的典型实现中,-1 当转换为unsigned int
时为 4,294,967,295,这确实 ≥ 1000。即使您在
code>unsigned
world,1000 - (4,294,967,295) = -4,294,966,295 = 1,001
这就是你得到的。这就是为什么当您将
unsigned
与signed
进行比较时,gcc
会发出警告。 (如果您没有看到警告,请传递-Wsign-compare
标志。)On a typical implementation where
int
is 32-bit, -1 when converted to anunsigned 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 compareunsigned
withsigned
. (If you don't see a warning, pass the-Wsign-compare
flag.)您正在进行无符号比较,即将 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.
为此,您需要了解运算符的优先级
关系运算符从左到右工作......
所以当它到来时
if(1000>-1)
时,首先它会将 -1 更改为无符号整数,因为 int 默认情况下被视为无符号数,并且它的范围大于有符号数
-1 将更改为无符号数,它变成了一个非常大的数字
For this you need to understand the precedence of operators
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
找到一种简单的比较方法,当您无法摆脱无符号声明(例如,[NSArray count])时,这可能很有用,只需将“unsigned int”强制为“int”即可。
如果我错了,请纠正我。
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.
该硬件设计用于比较有符号与有符号以及无符号与无符号。
如果需要算术结果,请先将无符号值转换为更大的有符号类型。否则,编译器将假定比较实际上是在无符号值之间进行的。
而-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.
在比较 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.