#include <stdio.h>
int main() {
unsigned int i = 23;
signed char c = -23;
if (i<c)
puts("TRUE");
return 0;
}
为什么下面程序的输出是TRUE,尽管我使用了可以存储-128到127的签名字符。
您的i < c
比较有两种不同类型的操作数,因此类型较小(秩较低(的操作数将转换为另一种类型。在这种情况下,由于-23
不能表示为unsigned int
;通常的算术转换;根据本(草案(C11标准的以下摘录中的第2段,它最终的值将大大大于+23
(实际上是UINT_MAX + 1 - 23
(:
6.3.1.3有符号和无符号整数
1将具有整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变
2否则,如果新类型是无符号的,则值由重复地加或减一个以上的最大值可以用新类型表示,直到值在新类型
3否则,将对新类型进行签名价值无法在其中体现;结果是实现定义的或实现定义的信号提出
您可以通过将c
分配给一个单独的unsigned int
并打印其值来查看此转换的实际操作,如以下代码所示。假设一个32位的unsigned int
,您可能会看到一个值4294967273
(实际上,它大于23
(。
#include <stdio.h>
int main()
{
unsigned int i = 23;
signed char c = -23;
unsigned int uc = c; // Add a diagnostic line ...
printf("%un", uc); // ... and show the value being used in the comparison
if (i < c) {
printf("TRUE");
}
return 0;
}
注意:这里两个变量(i
和c
(的相对大小有点像转移注意力;即使您将c
声明为signed int c = -23;
,由于常规算术转换(链接由Jonathan Leffler的评论提供(,您仍然会得到相同的结果——请注意,signed int
不能表示unsigned int
的所有可能值,因此最后一个"空心"项目符号将发挥作用。
为了进行比较,最小的变量(char,8位(必须提升到较大变量(整数,32位(的大小和有符号性。但这样一来,-23就变成了4294967273。这远远超过23。
如果将c
与签名的整数进行比较,则符号提升不会导致任何更改,并且测试的行为符合预期。