2017-08-25 222 views
2

爲什麼沒有在意外打印2D數組的一個維度時出現編譯時錯誤?此代碼爲什麼打印地址?

#include <stdio.h> 

void main() { 
    int i; 
    int arr[2][3] = { 1, 2, 3, 4, 5, 6 }; //<- Declared a 2D array 

    for (i = 0; i < 6; i++) { 
     printf("%d\n", arr[i]); // <- Accidently forgot a dimension 
    } 
} 

我應該收到編譯時錯誤,但我得到了一組地址!爲什麼?在編譯器的情況下,arr[0]是什麼意思?

+2

因爲* array *類型(這是'arr [i]'的類型)*衰減*到指針。 –

+0

它應該會產生警告(類型爲int *'的錯誤格式說明符'%d'),如果啓用的話。 http://coliru.stacked-crooked.com/a/8d995ce5a6a38cb2 – tkausl

+1

從技術上講,輸出是未定義的行爲,因爲'%d'不能用於指針。 –

回答

8

陣列型計算結果爲指針在大多數情況下,第一陣列元件的表達式(一個顯着的例外,除其他外,是sizeof操作符)。

在你的例子中,arr[i]數組類型。所以它的計算結果爲int (*)[](指向數組的指針)類型的指針。這就是打印的內容。用%d打印指針是未定義的行爲,因爲printf()將讀取指針,就好像它是int一樣。

1

菲利克斯帕爾曼的答案解釋了觀察到的行爲。

關於你的第二個問題:你沒有得到警告的原因是你沒有要求他們。

編譯器在默認情況下非常寬鬆,並且會接受包含明顯未定義行爲的破壞代碼。這個特定的不明顯,因爲printf()在初始格式字符串之後接受任何數量的額外參數。

您可以指示您的編譯器發出許多有用的警告,以避免愚蠢的錯誤並檢測到非顯而易見的編程錯誤。

  • gcc -Wall -Wextra -Werror
  • clang -Weverything -Werror
  • 選項/W3/W4與Microsoft Visual Studio。

gccclang會抱怨數組arr馬虎初始化。它應該是:

int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; 

打印循環的確令人驚訝,你真的打算用單循環打印數組嗎?

還要注意,沒有參數的main的標準原型是int main(void)