为啥指针+1包含的内存地址与被指向的值的地址+1不同
Posted
技术标签:
【中文标题】为啥指针+1包含的内存地址与被指向的值的地址+1不同【英文标题】:Why memory address contained by pointer +1 is different from address of value being pointed + 1为什么指针+1包含的内存地址与被指向的值的地址+1不同 【发布时间】:2016-07-21 20:19:23 【问题描述】:指针存储指向的值的内存地址,因此指针包含的内存地址与值的内存地址相同。因此,将 1 加到这两个内存地址应该会产生相同的结果,但这是不会发生的。为什么? 这是代码
int main()
int ages[] = 23, 43, 12, 89, 2;
int *cur_ages = ages;
printf("\n&cur_ages=%p, &cur_ages+1=%p", &cur_ages, &cur_ages+1);
printf("\n&ages=%p, &ages+1=%p", &ages, &ages+1);
printf("\ncur_ages=%p, cur_ages+1=%p", cur_ages, cur_ages+1);
printf("\n*cur_ages=%d, *cur_ages+1=%d", *cur_ages, *(cur_ages+1));
return 0;
输出是
&cur_ages=0x1ffff85f3d0, &cur_ages+1=0x1ffff85f3d8
&ages=0x1ffff85f3dc, &ages+1=0x1ffff85f3f0
cur_ages=0x1ffff85f3dc, cur_ages+1=0x1ffff85f3e0
*cur_ages=23, *cur_ages+1=43
&ages+1 不等于 cur_ages+1。为什么?
【问题讨论】:
将非void*
参数传递给printf("%p")
的未定义行为。您可能认为这是迂腐的,但各种对象的类型确实是问题的核心。
指针不是地址,指针加1不等于地址加1。
@user2357112:在 C 语言中,指针值是一个“地址”。这就是 C 标准中使用“地址”一词的方式。 C“地址”与机器级“地址”不同。
谨慎措辞,@user2357112,指针是具有类型的地址。给指针加 1 会增加其类型的大小。
【参考方案1】:
指针算法通过给定值乘以它指向的类型的大小来增加指针的值。
所以当你这样做时:
&ages+1
您获取ages
(类型为int [5]
)的地址并将sizeof(ages)
添加到指针值。假设 sizeof(int)
为 4,这会将 20 添加到指针值。
同样,当你这样做时:
cur_ages+1
这里,cur_ages
指向一个 int
,所以加 1 会将 sizeof(int)
添加到指针值。
【讨论】:
这是一个很好的例子,说明为什么数组和指针不是一回事。【参考方案2】:&cur_ages 是 cur_ages 在堆栈中存储的地址。由于 &cur_ages+1 比 8 大,我假设这是在 64 位模式下完成的,其中指针的大小为 8 个字节。
&ages 类似于声明 int (*ptr_to_ages)[5],其中 ptr_to_ages 是指向 5 个整数数组的指针,它可以是指向矩阵第一行的指针,其中每行是 5 个整数的数组. &ages = 存储数组第一个成员的地址。正如 dbush 的回答中提到的,由于年龄是 5 个整数的数组,所以 &ages+1 指向在年龄的 5 个整数之后的 5 个整数数组,所以 + 5 * 4,其中 4 是整数的大小,实际上与指向矩阵第二行的指针相同,其中每一行都是 5 个整数的数组。
示例代码不会打印出年龄和年龄+1,它们的区别是 sizeof(int) 而不是 5 * sizeof(int)。如果没有年龄的 & 前缀,则数组的大小无关紧要。
cur_ages 和 cur_ages+1 指向年龄的第一个和第二个整数,正如预期的那样。
*cur_ages 和 *(cur_ages+1) 是年龄的第一个和第二个整数值。
【讨论】:
【参考方案3】:这里发生了几件事。
&cur_ages
是指向值的指针的地址,而不是值的地址。由于 C 中的(arguably odd) semantics of array names,&ages
是一个值的地址。
指针算法 (&<anything>+1
) 适用于整个项目,而不是字节。因此,将 1 添加到 int *
将添加 sizeof(int)
字节,而不是一个字节。
【讨论】:
抱歉,从初学者的角度来看,这是一个糟糕的答案 :) 这部分的特别之处&cur_ages is the address of a pointer to a value, not the address of a value.
以上是关于为啥指针+1包含的内存地址与被指向的值的地址+1不同的主要内容,如果未能解决你的问题,请参考以下文章