2010-08-01 121 views
3

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

是什么原因?

+0

为什么不能简单地用于'(d = 0; d fredoverflow 2010-08-01 18:06:10

+2

也许这是一个有用的例子,说明在C中正确编程有多困难。鉴于此,这确实是一个很好的例子。 – 2010-08-01 18:13:32

+0

这个问题是[Gowri Korumar的C谜题](http://www.gowrikumar.com/c/)的一部分,它汇编了50个非常有教育意义的C语言问题。我从过去的知识和研究中回答了前25个问题,以帮助解答:[C puzzle解答](http://codeitdown.com/c-puzzles-answered/)。 – JoseV 2013-12-27 05:12:51

回答

5

当您执行比较d <= (TOTAL_ELEMENTS-2)时,将执行类型转换d的类型是signed int,而(TOTAL_ELEMENTS-2)的类型是size_t,它是一个无符号类型。 C的规则说,当一个运算符有一个有符号和无符号参数,并且无符号参数的大小大于或等于有符号参数时,那么该有符号参数将转换为无符号。

也就是说,比较最终为:

(size_t) d <= (TOTAL_ELEMENTS-2) 

而且由于size_t是无符号,(size_t) -1是一个非常,非常大的数量,而不是-1了。对于32位的size_t,它将是2 -1 = 4,294,967,295。

为了解决这个问题,你可以明确地投的右手边有符号整数:

d <= (int) (TOTAL_ELEMENTS-2) 

或者,更好的,刚刚摆脱怪异负索引和这样的。

为了将来的参考,打开所有的编译器警告你可以。

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

除了将宏的结果强制转换为int以外,从头开始将'size_t'用于'd'并使用适当的边界'0'作为开始,将'd 2010-08-01 22:20:13

6

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

+0

是的......你不应该混合签署/未签名的任务或比较没有适当的原因,在这种情况下,明确铸造就位。另外,如果设置了适当的警告级别,大多数编译器应该已经发出警告。 – smichak 2010-08-01 18:06:21

1

原因是循环从未执行。这是因为TOTAL_ELEMENTS返回一个size_t,一个无符号类型。

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

0

你需要做到以下几点:

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

sizeof(...)产生一个无符号值。

3

起初,我不知道:GCC,例如,会如果打开-Wall -Wextra打印警告。但是,当我用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,因此永远不会执行循环体。

0

只需改变

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

随着

​​
+0

你真的把它弄错了。数组索引应该总是“size_t”。他应该把'd'改成'size_t'并做适当的索引,并且所有的模糊都会消失。 – 2010-08-01 22:16:58