循环从-1开始不打印任何东西

这个程序应该打印出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; } 

为什么这个程序不显示任何输出?

sizeof返回一个无符号整数,所以TOTAL_ELEMENTS也是无符号的。

d签名。 最初, d-1 。 但是,比较的时候, d是隐含的无符号的types转换,所以当与TOTAL_ELEMENTS比较时,它不再是-1 ,它实际上是UINT_MAX (在我的机器上是4294967295 ,但是对于其他的可能是不同的)。

也,

如果你想解决这个问题, TOTAL_ELEMENTStypes转换为int

 for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) 

这将打印:

 23 34 12 17 204 99 16 

正如你所期望的那样。 您也可以查看有关未签名和有符号整数的比较操作,以获取有关无符号签名比较主题的更多信息。

值得注意的是,打开编译器警告可以帮助你弄清楚发生了什么事情(正如海德在他的评论中所观察到的那样):

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

或者,为什么不从0开始d并运行到TOTAL_ELEMENTS - 1呢? 你甚至可以删除这个types转换,只有在d = -1情况下才需要。

 for(d = 0; d < TOTAL_ELEMENTS; d++) printf("%d\n", array[d]); 

作为脚注,以下是相关的C99标准摘录:

  1. 6.3.1.8p2定义了从签名到无符号types的转换。

    如果具有无符号整数types的操作数具有大于或等于另一操作数types的等级,则具有有符号整数types的操作数被转换为具有无符号整数types的操作数的types。

  2. 6.3.1.3p2定义了如何完成转换:通过将UINT_MAX + 1添加到有符号表示中。

    如果新types是无符号的,则通过重复join或减去新types中可以表示的最大值之一来转换该值,直到该值在新types的范围内。

    所以对于这个场景, -1 => -1 + (UINT_MAX + 1) = UINT_MAX

我的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 intd是有signed int 。 因为(unsigned int)(-1) > (TOTAL_ELEMENTS-2) ,所以这个expression式对于d的初始值总是为false

不同整数types之间的二进制操作在由所谓的常规算术转换定义的“公共”types内执行。 所以int d是用值-1初始化的单types。 当转换为unsigned int时,它将返回最大的unsigned int,这比TOTAL_ELEMENTS返回的值大得多。