打印数组元素

时间:2010-08-01 17:58:39

标签: c arrays

以下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;
}

是什么原因?

6 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:5)

进行比较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

答案 2 :(得分:3)

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

$ gcc -Wall -Wextra -Os a.c
a.c: In function `main':
a.c: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,因此循环体永远不会被执行。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

您需要执行以下操作:

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

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

答案 5 :(得分:0)

只需更改

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

使用

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