从 -1 开始的循环不打印任何内容

Loop starting at -1 doesn't print anything

这个程序应该打印出 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 returns 一个无符号整数,所以 TOTAL_ELEMENTS 也是无符号的。

d 已签名。最初,d-1。但是,在进行比较时,d 被隐式类型转换为 unsigned,因此在与 TOTAL_ELEMENTS 进行比较时不再是 -1,它实际上是 UINT_MAX(这是 4294967295 在我的机器上,但对于其他人可能会有所不同)。

此外,

如果你想解决这个问题,请将 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 在他的 中观察到的):

$ 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 标准摘录:

  1. 6.3.1.8p2 定义了从有符号类型到无符号类型的转换。

    If the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

  2. 6.3.1.3p2 定义如何完成转换:通过将 UINT_MAX + 1 添加到已签名的表示形式。

    If the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

    因此 -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 intdsigned int。这使得表达式总是 false 用于 d 的初始值,因为 (unsigned int)(-1) > (TOTAL_ELEMENTS-2).

不同整数类型之间的二元运算在由所谓的通常算术转换定义的 "common" 类型中执行。所以 int d 是用值 -1 初始化的 singed 类型。当转换为 unsigned int 时,它将 return unsigned int 的最大值远大于 return 编辑的值 TOTAL_ELEMENTS.