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]
不同?
答案 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]
不同,因为它指的是一个完全不同的东西(见上文)。