2013-02-28 113 views
4
#include <stdio.h> 

int main(void) 
{ 
    int a[5] = { 1, 2, 3, 4, 5 }; 

    int *ptr = (int*)(&a + 1); // what happens here ? 

    printf("%d %d\n", *(a + 1), *(ptr - 1)); 

    return 0; 
} 

我預期答案是1但是會得到5 .. 爲什麼?int * ptr =(int *)(&a + 1);

+3

當然,輸出包含兩個數字,而不是一個? – NPE 2013-02-28 17:08:19

+1

您正在接受一個數組的地址,並假定它與第一個元素的地址是一樣的。不是。類型不同,指針運算也不同。 – 2013-02-28 17:13:25

+0

oh yea ..我只是在談論*(ptr - 1).. 預計o/p由我 - 2 1 實際o/p是 - 2 5 .. 反正Daniel菲捨爾解釋它! 謝謝 – 2013-02-28 17:19:27

回答

9
int *ptr = (int*)(&a + 1); // what happen here ? 

數組的地址被佔用,然後加1到它,產生的指針指向a開頭的sizeof a字節。然後該指針被轉換爲int*,並將其分配給ptr。用

int *ptr = &a[5]; 

可以實現這種情況。

然後ptr - 1ptr之前指向sizeof(int)字節,也就是要&a[4]一個指針,和*(ptr - 1)a[4]

指針算術是以「指針大小」爲單位完成的。由於&a是指向數組5 int - int (*)[5]的指針,因此將其加1會使其移動5*sizeof(int)字節。

+0

ok .. int * ptr =(int *)(&a + 2); 然後ptr-6會產生相同的結果。 非常感謝:-) – 2013-02-28 17:17:19

+1

也許是的,也許沒有。 '(&a + 2)'是未定義的行爲,因爲指針運算只在結果指針指向同一個數組或指向結尾的指針時定義。 '(&a + 2)'會在結尾處指出兩點。但在實踐中,儘管行爲是未定義的,但實現的行爲與您期望的相似,幾乎是100%。 – 2013-02-28 17:20:27

+0

哦好吧.. (&a + 2)可能不會指向過去的兩個結尾的可能性非常小。所以最好避免這種情況。 感謝Daniel的建議。 – 2013-02-28 17:28:08

5

&a是指針指向int[5]的指針,因此&a + 1又是指向int[5]的指針。鬆&,所有應罰款(和你也將不再需要施法):

int *ptr = a + 1; 
+0

不,'&a'是一個'int(*)[5]',而不是'int **'。 – 2013-02-28 17:13:57

+0

@DanielFischer true。 – 2013-02-28 17:14:23

+0

@IvayloStrandjev不是&a ==&&a [0]? – Arpit 2013-02-28 17:18:06

1
int *ptr = (int*)(&a + 1); // what happen here ? 

陣列的第一元件的=地址:A [0](INT的地址)

&一個=陣列的地址與 「一」 一個,相同的值,但是類型是陣列的地址,所以表達式「(&a + 1)」是指向下一個數組「a」的指針。 (ptr-1):指向ptr的前一個int的指針,表示數組「a」的最後一個元素的指針。

相關問題