以下C程序的预期输出是打印数组元素。但当它真的运行时,它不会这样做。

#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;
}

原因是什么?

最佳答案

进行比较时,将执行类型转换。d <= (TOTAL_ELEMENTS-2)属于d类型,signed int属于(TOTAL_ELEMENTS-2)类型,这是一种无符号类型。c的规则规定,当运算符有一个有符号和一个无符号参数,且无符号参数的大小大于或等于有符号参数时,则将有符号参数转换为无符号参数。
也就是说,比较结果是:

(size_t) d <= (TOTAL_ELEMENTS-2)

因为size_t是无符号的,size_t是一个非常非常大的数字,不再是-1。对于32位(size_t) -1来说,它是232-1=4294967295。
要解决此问题,可以显式地将右侧强制转换为带符号的int:
d <= (int) (TOTAL_ELEMENTS-2)

或者,更好的是,摆脱怪异的负面索引等等。
为了以后的参考,打开所有编译器警告。例如,如果您打开size_t,gcc将打印一个警告:
$ gcc -o arrayprint -Wall -Wextra -ansi arrayprint.c
arrayprint.c: In function ‘main’:
arrayprint.c:11: warning: comparison between signed and unsigned

10-05 19:13