该程序应该打印出array
的元素,但是当它运行时,不显示输出。
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = { 23, 34, 12, 17, 204, 99, 16 };
int main() {
int d;
for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++)
printf("%d\n", array[d + 1]);
return 0;
}
为什么这个程序没有显示任何输出?
答案 0 :(得分:154)
sizeof
返回无符号整数,因此TOTAL_ELEMENTS
也是无符号的。
d
已签名。最初,d
是-1
。但是,在进行比较时,d
隐式强制转换为无符号,因此与-1
进行比较时不再是TOTAL_ELEMENTS
,实际上是UINT_MAX
(4294967295
我的机器上有{1}},但其他人可能会有所不同)。
另外,
如果您想解决这个问题,请将TOTAL_ELEMENTS
转换为int
:
for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++)
这将打印:
23
34
12
17
204
99
16
正如您所期望的那样。您可能还想查看Comparison operation on unsigned and signed integers以获取有关签名无符号比较主题的更多信息。
值得注意的是,打开编译器警告会帮助你弄清楚发生了什么(正如hyde在comment中所观察到的那样):
$ gcc -Wall -Wextra test.c
test.c:7:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
for(d = 0; d < TOTAL_ELEMENTS; d++)
~ ^ ~~~~~~~~~~~~~~
1 warning generated.
或者,为什么不在d
处开始0
并转而转到TOTAL_ELEMENTS - 1
?您甚至可以放弃类型转换,这仅适用于d = -1
的角落情况。
for(d = 0; d < TOTAL_ELEMENTS; d++)
printf("%d\n", array[d]);
作为脚注,以下是相关的C99标准摘录:
6.3.1.8p2 定义了从有符号到无符号类型的转换。
如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则 带有符号整数类型的操作数转换为 具有无符号整数类型的操作数。
6.3.1.3p2 定义了转化的方式:将UINT_MAX + 1
添加到已签名的表示中。
如果新类型是无符号的,则通过重复加或减一个最大值来转换该值 可以用新类型表示,直到值在 新类型的范围。
所以-1
=&gt;对于这种情况,-1 + (UINT_MAX + 1)
= UINT_MAX
。
答案 1 :(得分:38)
我的gcc输出此警告:
warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
for(d = 0; d < TOTAL_ELEMENTS; d++)
表示(TOTAL_ELEMENTS-2)
为unsigned int
而d
为signed int
。这使得false
的初始值始终为d
,因为(unsigned int)(-1) > (TOTAL_ELEMENTS-2)
。
答案 2 :(得分:5)
不同整数类型之间的二进制运算是在&#34; common&#34;由所谓的通常算术转换定义的类型。所以int d是用值-1初始化的singed类型。当转换为unsigned int时,它将返回unsigned int的最大值,该值远大于返回的值 TOTAL_ELEMENTS。