2010-08-01 160 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