知道初始地址的指针的地址

Address of a pointer knowing the initial address

我有以下代码:

int main(){
int tab[5]={10, 20, 30, 40, 50};
int *ptr;
ptr=tab+4;
printf("%d,%#x,%#x. \n",*ptr-1,&tab,ptr);
return 0;}

"tab" 位于从 dress 0x28FEF8 开始的内存区域。

我知道*ptr-1的值为49,&tab的值为0x28FEF8

有人能解释一下为什么 "ptr" 的值是 0x28FF08 吗?我猜应该是 0x28FEFC。

提前致谢!

如果我们"draw"你的数组在内存中的布局,它将看起来像

+----+----+----+----+----+
| 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+

然后你需要记住,数组自然会衰减到指向其第一个元素的指针,即 tab 等于 &tab[0]。然后你需要记住,对于任何数组或指针 a 和索引 i,表达式 a[i] 正好等于 *(a + i)。由此很容易推断出 tab + 4 等于 &tab[4],即指向第五个元素的指针。

因此,如果我们再次绘制数组,但现在使用指针:

+----+----+----+----+----+
| 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+
^                   ^
|                   |
&tab[0]             &tab[4]
|
&tab

如果 &tab[0] 等于 0x28fef8 那么 &tab[4] 等于 0x28fef8 + sizeof(int) * 4,因为它指向 int 数组的索引 4,它确实是 0x28ff08.

请注意,虽然 &tab[0]&tab 指向相同的位置,但它们在语义上是不同的。 &tab[0] 是指向单个元素的指针,类型为 int *,而 &tab 是指向数组的指针,类型为 int (*)[5].


在相关说明中,打印 void * 指针的正确格式是 "%p"。所以你的印刷真的应该是

printf("%d,%p,%p. \n", *ptr-1, (void *) &tab, (void *) ptr);

请注意,确实需要转换为 void *