2013-02-28 143 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”的最后一个元素的指针。

相关问题