2016-08-04 49 views
0

我的代碼是這樣的我的程序的輸出是混亂

int main() 
{ 
    unsigned int x [4] [3] = 
    {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}; 
    printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3); 
} 

輸出的所有3個值都相同誰能告訴我爲什麼?

+0

使用錯誤的格式說明符是未定義的行爲。 – mch

+0

錯誤的格式說明符%u是用於unsigned int的。 –

+0

'x + 3'的類型是'unsigned int(*)[3]'(一個指針),'*(x + 3)'和'*(x + 2)+ 3'的類型是'unsigned int *'。所有3個都不是'unsigned int',而是指針,所以你應該使用'%p'並且轉換爲'(void *)'。 – mch

回答

2

首先 - 正如其他人所指出的那樣 - 您需要使用正確的格式說明符,並將這些值轉換爲指針。


現在至於爲什麼他們都給出相同的價值。這裏x是一個數組。其元素的類型是unsigned int[3]。即xunsigned int[3]陣列的陣列 。

首先,x + 3 給出數組中第四個元素的地址。那就是{10, 11, 12}的 地址。該數組在內存中的地址將是其內存中第一個元素的地址。這是內存中10的地址。請注意,該值爲int (*) [3],即address of an unsigned int[3] array

二,* (x + 3) 相當於x [3],它是第四個元素,它是unsigned int[3]。 它是陣列{10, 11, 12}。該值指向 數組{10, 11, 12}的第一個元素。也就是說,這個值指向10。請注意,此值爲unsigned int[3]

*(x+2) + 3:這裏*(x + 2)相當於x[2]這是一個unsigned int[3],這是{7, 8, 9}陣列, 當你做一個+ 3你正在又一次的10地址。請注意,此值爲unsigned int[3]

因此,你會發現在所有三種情況下,你的結果都是在內存中的相同地址,即存儲10的地址 - 即使你在不同的時間表示不同的東西;第一個是unsigned int (*)[3],第二個和第三個是unsigned int[3]

0

蒸餾水未定義行爲:

printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3); 

所有額外的參數必須是unsigned int,但2D是unsigned int (*)[3],三維是unsigned int *,第四是unsigned int *了。

1

你得到錯誤的值,因爲你做指針算術錯誤。
xunsigned int[4][3]型,長度爲4的陣列,其中每個部分是本身長度3.

因此,什麼是x+3的陣列?它是x中最後一個成員的地址(請記住x的成員是數組)。
因此*(x+3)本身就是一個數組。但是當你將它們作爲函數參數傳遞時,數組會發生什麼?他們衰變成指針。所以你看到中第一個元素的地址數組,被printf中錯誤的類型說明符所篡改。

好吧,讓我們來看看元素x[2][3]。這將是*(*(x+2)+3)這種表示,全部相當於*(&x[0][0] + 2*3 + 3)