2017-10-07 135 views
1
int main(void) { 
    unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)}; 
    printf("%d, %u, %u, %u \n",**x, **(x+1), **(x+2), **(x+3)); 
    return 0; 
} 

上述代碼的輸出是3,12,0,0,0。 因爲x存儲數組的第一個元素的地址,它不應該是1,4,7,17​​嗎?**如何在2維數組中工作?

當我試圖打印

printf("%u, %u \n", x, &x[0][0]); 

它顯示了相同的地址2108666688,2108666688

但是,當我嘗試打印使用

for(int i = 0; i<4; ++i) 
{ 
    for(int j = 0; j<3 ; ++j) 
    { 
     printf("%d ",x[i][j]); 
    } 
    printf("\n"); 
} 

我看到輸出

數組
3 6 9 
12 0 0 
0 0 0 
0 0 0 

那麼,這裏究竟發生了什麼?爲什麼數字沒有正確指定給數組?

+2

「{(1,2,3),(4,5,6),(7,8,9),(17,11,12)}」並不會根據您的預期進行評估。認真對待編譯器的警告。 – alk

+1

是的,總是使用新的代碼 – jku

回答

6
unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)}; 

在功能上等同於:

unsigned int x[4][3] = {3, 6, 9, 12}; 

因爲comma operator是在這裏工作!逗號運算符評估其所有操作數並得出其最後一個操作數的結果。

所以你看到的輸出是預期的。你可能的意思是:

unsigned int x[4][3] = {{1,2,3},{4,5,6},{7,8,9},{17,11,12}}; 
+0

[「逗號運算符',''做什麼?](https://stackoverflow.com/q/52550/995714) –

+0

正如答案中所述,它返回所有操作數的最後一個數字,即(2,3,7,4)返回4 – BloomBlack

1

請記住,數組自然衰變爲指向其第一個元素的指針。這意味着在你的情況下,x本身與&x[0]相同。

由於x是一個數組數組,因此&x[0]的類型是一個指向數組的指針,在這種情況下爲unsigned int (*)[3]。解引用這個指針是一個數組(類型爲int [3]),該數組又可以衰減爲指向其第一個元素的指針。

雙引用的功能是簡單地解引用這兩個指針,從而產生第一個數組的第一個元素,即x[0][0]

,出現這種情況是3代替1是因爲你初始化使用被使用逗號表達式這導致3(1, 2, 3)的元素。

什麼你可能想要做的就是使用大括號的「內部」陣列,以及:

unsigned int x[4][3] = {{1,2,3},{4,5,6},{7,8,9},{17,11,12}}; 

現在**x將導致1代替。

另一件要記住的是,對於任何數組或指針x和索引i,表達x[i]等於*(x + i)

1

由於因爲我認爲一個錯字(有使用括號代替括號)此聲明

unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)}; 

等同於

unsigned int x[4][3] = { 3, 6, 9, 12 }; 

陣列的所有其他元素爲零初始化。

作爲導致陣列看起來就像是顯式地初始化以下方式

unsigned int x[4][3] = { { 3, 6, 9 }, { 12, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; 

即例如這個表達式

(1,2,3) 

是與產生的值的逗號運算符的表達式最後一個操作數。

從C標準(6.5.17逗號運算符)

2逗號操作者的左操作數作爲空隙 表達式求值;在它的評估和右操作數的 之間有一個序列點。 然後評估右操作數; 結果有其類型和值

例如,考慮

unsigned int x = (1, 2, 3); 
printf("x = %u\n", x); 

要獲得期望的結果,你必須用大括號代替括號。例如

unsigned int x[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {17,11,12} };