2012-07-26 82 views
1

我在網上找到了這段代碼。該程序的輸出是 字符串 字符串 字符串 有人可以請解釋我爲什麼第一個secon和第三個printf語句打印相同的輸出,即使他們的參數不同?c程序輸出說明

#include<stdio.h> 
int main() 
{ 
char a[2][3][3] = {'s','t','r','i','n','g'}; 
printf("%s\n", *a); 
printf("%s\n", a); 
printf("%s\n", **a); 
getchar(); 
return 0; 
} 
+0

@chris數組的總大小爲18,初始化爲6個元素,所有後面的元素都是'0'。 – ecatmur 2012-07-26 13:52:46

+0

@chris我知道。但是我沒有在網上發現自己編寫的代碼。 – Prateek 2012-07-26 13:54:39

+0

@ecatmur,哎呀,沒錯。出於某種原因,我認爲所有的元素都被設置了。 – chris 2012-07-26 13:54:42

回答

8

由於這是3維陣列,*aa(數組的數組的數組),和**a都指的是相同的地址。前兩種的printf()類型不正確,但在所有情況下,它將被解釋爲平坦的char *字符串。如果您在編譯器上顯示警告,則應該看到一些關於格式字符串和類型不匹配的信息。

請記住,*a就像a[0]**a就像a[0][0]。這可能更容易看出他們爲什麼引用相同的地址。

2

您正在將char (*)[3]char (*)[3][3]視爲char *。由於它們指向相同的地址,並且(在這種情況下)它們具有相同的內存中表示,所以它們被讀取爲與指向該地址的char *相同。

這是未定義的行爲;不要這樣做。

1

讓我們來看看char a[2][3][3]是如何鋪設在內存中的。在我的機器裏它是這樣的:

0x7fffffffe220: 0x73 0x74 0x72 0x69 0x6e 0x67 0x00 0x00 
0x7fffffffe228: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffe230: 0x00 0x00 

它的唯一很自然的因爲所有的數組實際上都是線性的。這些尺寸意味着什麼,與像a[i][j][k]這樣的數組索引配合使用。但從記憶的角度來看,它只是一個棘手的方法來計算偏離基地址。

現在,因爲你已經把它定義爲三維陣列,你可能想知道的C如何初始化後把這個數組:

{{{0x73, 0x74, 0x72}, {0x69, 0x6e, 0x67}, {0x0, 0x0, 0x0}}, {{0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}} 

現在,讓我們看看我們在這裏...

printf被調用來打印一個sting並傳遞一個地址。那麼,什麼printf的都行,就是抓住該地址,並嘗試,直到它看到一個空

每次調用print同樣的事情,因爲:

(gdb) x/10xb **a 
0x7fffffffe220: 0x73 0x74 0x72 0x69 0x6e 0x67 0x00 0x00 
0x7fffffffe228: 0x00 0x00 
(gdb) x/10xb *a 
0x7fffffffe220: 0x73 0x74 0x72 0x69 0x6e 0x67 0x00 0x00 
0x7fffffffe228: 0x00 0x00 
(gdb) x/10xb a 
0x7fffffffe220: 0x73 0x74 0x72 0x69 0x6e 0x67 0x00 0x00 
0x7fffffffe228: 0x00 0x00 

最後一個忠告,做這樣編碼。如果你足夠聰明,就單單用指針來做每件事。但它更容易出錯。因此,雖然底層將幾乎可以互換地處理指針和數組,但您堅持使用開始的內容。如果可以用手操縱東西,就像指針一樣處理。如果你想通過索引進行更嚴格的操作,就像處理數組一樣處理。