为什么“*(& arr + 4)”与“& arr [4]”不同?

时间:2014-06-02 07:21:33

标签: c pointers reference

int arr[] = { 0, 1, 2, 3, 4, 5 };

我正在执行地址操作测试,以增加我对ref和deref的理解。 这里有很多困惑。

我发现&*(arr+4)使用与&arr[4]相同的地址,但我从未见过&*

这样的作业

此外,我认为*(&arr+4)使用与&arr+4相同的地址,但这对我没有任何意义。

我找不到相关信息,所以我在这里问一下,为什么*(&arr+4)使用与&arr+4相同的地址,为什么*(&arr+4)&arr[4]不同?

1 个答案:

答案 0 :(得分:11)

arr是一个数组:

arr: int[6]
[0|1|2|3|4|5]

sizeof arr&arr以外的表达式中使用时,数组会衰减到指向数组第一个元素的指针:

(arr+0): int *
[*]
 |
 v
[0|1|2|3|4|5]

当一个整数值被添加到指针时,你会得到一个指向内存中(sizeof (T)) * n字节的地址的指针(其中T是指针指向的类型,而n是添加到指针的积分值):

(arr+4): int *
        [*]
         |
         v
[0|1|2|3|4|5]

当指针被取消引用时,您将获得指向的值:

*(arr+4): int
          4 /* specifically, the 4 in the fifth position in `arr` */
[0|1|2|3|[4]|5]

当地址取自int时,你会得到一个指向那个int的指针:

&*(arr+4): int *
        [*] /* notice, this is the same as (arr+4) */
         |
         v
[0|1|2|3|4|5]

数组索引等效于指针添加,后跟解除引用:

arr[4] == *(arr+4) /* see above for definition of *(arr+4) */

所以是的...... &*(arr+4)&arr[4]相同。

当获取数组的地址时,你会得到一个指向数组的指针:

&arr: int (*)[6]
[*] /* points to the array as a whole, not the first element of the array */
 |
 v
 [0|1|2|3|4|5]

当你增加指针时,适用相同的规则:

                                    &arr + 4: int(*)[6]
               /*points into some memory that*/    [*]
               /* isn't part of the array... */     |
               /*  undefined behaviour       */     v
[0|1|2|3|4|5][x|x|x|x|x|x][x|x|x|x|x|x][x|x|x|x|x|x][x|x|x|x|x|x]

由于这有未定义的行为,因此如果不参考底层机器架构和编译器实现,就无法对其进行推理。

如果我们想象它已被很好地定义(如果arr是更大数组的一部分就是这种情况)......我们可以继续。取消引用指向数组的指针会再次给出数组:

             /*the 5th array in this array of arrays*/ *(&arr+4): int[6]
   [0|1|2|3|4|5][x|x|x|x|x|x][x|x|x|x|x|x][x|x|x|x|x|x][[x|x|x|x|x|x]]

您会发现*(&arr+4)(&arr+4)具有相同的地址,因为*(&arr+4)衰减为指向*(&arr+4)的第一个元素的指针,并且数组从其开始第一个元素,所以指向数组开头的指针和指向数组第一个元素的指针是相同的。

*(&arr+4)&arr[4]不同,因为它指的是一个完全不同的东西(见上文)。