打印数组元素

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

#include #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)的类型为size_t ,这是一个无符号类型。 C的规则表明,当运算符具有signed和unsigned参数,并且unsigned参数的大小大于或等于signed参数时,signed参数将转换为unsigned。

也就是说,比较结果如下:

 (size_t) d <= (TOTAL_ELEMENTS-2) 

因为size_t是无符号的,所以(size_t) -1是一个非常非常大的数字,不再是-1。 对于32位size_t ,它将是2 32 - 1 = 4,294,967,295。

要解决此问题,您可以显式地将右侧转换为signed int:

 d <= (int) (TOTAL_ELEMENTS-2) 

或者,更好的,只是摆脱奇怪的负面索引等。

为了将来参考,请打开所有编译器警告 。 例如,如果你打开-Wall -Wextra ,gcc会打印一个警告:

 $ gcc -o arrayprint -Wall -Wextra -ansi arrayprint.c arrayprint.c: In function 'main': arrayprint.c:11: warning: comparison between signed and unsigned 

TOTAL_ELEMENTS未签名。 -1,当转换为unsigned时,是一个非常大的数字,不小于6.因此,你的循环永远不会运行。

起初,我不知道。 但是当我使用GCC编译它时,显然很明显:

 $ gcc -Wall -Wextra -Os ac ac: In function `main': ac:11: warning: comparison between signed and unsigned 

所以你有一个比较如下:

 (int) -1 <= (size_t) 5 

由于其中一种类型是有符号的,另一种是无符号的,因此首先需要将它们转换为通用类型。 在这种情况下,它是size_t 。 这样做:

 (size_t) -1 <= (size_t) 5 

现在-1无法以无符号类型表示。 因此,添加了2 ^ 32(或者有多个位size_t ),这使得它为4294967295.所以比较实际上是:

 4294967295 <= 5 

这是false ,因此循环体永远不会被执行。

原因是循环永远不会执行。 这是因为TOTAL_ELEMENTS返回size_t,一个无符号类型。

您可以通过将(TOTAL_ELEMENTS-2)转换为int来解决此问题。

您需要执行以下操作:

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

因为sizeof(...)产生无符号值。

简单地改变

 #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) 

 #define TOTAL_ELEMENTS (int)(sizeof(array)/sizeof(array[0]))-2