打印数组元素
以下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