【问题标题】:Why are the values different? C++ pointer为什么价值观不同? C++ 指针
【发布时间】:2019-09-26 01:26:16
【问题描述】:

我在谷歌上搜索了一个解决方案来找出 C++ 中数组的长度。我找到的解决方案之一是这个

int arr[] = {1,2,3,4,5,6};
int size = *(&arr+1)-arr; //size is the length of the array

我对@9​​87654323@ 和arr 感到困惑,因为两者都给出了数组的基地址。再次谷歌,发现&arr + 1 给出了不属于数组的下一个内存块的地址,而arr + 1 给出了数组中下一个元素的地址。

我写了以下代码来测试&arrarr之间的区别:

int arr[] = {1,2,3,4,5,6};
printf("value of &arr + 1 - &arr = %d\n", &arr + 1 - &arr);
printf("value of *(&arr + 1) - arr = %d\n", *(&arr + 1) - arr);

第一个printf 的答案是1,而第二个printf 的答案是6。这是让我困惑的部分:既然&arrarr 都持有同一个数组的基地址,为什么结果不同?

【问题讨论】:

  • &arr + 1 - &arr = &arr - &arr + 1 = 1。
  • @solarflare -- 不是这样,*(&arr + 1) - arr == 6。为什么? &arr指向 char [6] 数组的指针,因此 &arr + 1指针(指向紧随其后的地址)char [6] 数组。当你取消引用 pointer to array 时,你会得到一个 array,它通过在访问时转换为指针是int(在这种情况下)的地址在arr 之后。所以*(&arr + 1) - arr 将给出int 数组中的元素数,就像sizeof arr / sizeof *arr 一样。
  • 注意:这里更有用的可能是打印出您正在工作的对象的地址(在&arr +1 的情况下为非对象),以查看它们在内存中的布局位置将是printf 中的%p 格式选项。
  • 你忘记了类型系统。指针上的+1 表示指向指针所指向的下一个事物。这并不意味着 +1 字节。

标签: c++ arrays pointers


【解决方案1】:

既然“&arr”和“arr”都持有同一个数组的基地址,为什么结果不一样?

因为类型不同。指针运算受指针类型的影响,更具体地说,受指向对象类型的影响。

&arr 是一个指向 6 个 int 数组的指针。将 1 加到下一个 6 个整数数组(如果它是数组数组的元素)。

arr虽然是一个数组,但在使用它的值时会衰减为指向数组第一个元素的指针,例如在指针算术表达式中。衰减后的值是一个指向 int 的指针,加 1 会将指针移动到下一个整数。

附:您可以改用std::size。或std::extent pre-C++17。或者sizeof arr / sizeof *arr pre-C++11。

*(&arr + 1) - arr 可能有效,但在技术上通过一个过去的指针(指向一个不存在的对象)间接,这通常是未定义的行为。考虑到该值仅用于衰减到指针,我不确定该规则是否可能有一些例外。

【讨论】:

  • 更好的是,您可以使用std::arraystd::vector
  • 让我好奇的是这一切到底有多合法。指针算法只在对象内有效。过去的对象技巧是否有特殊豁免?哈!你去吧。应该早点点击查看编辑!我也找不到异常。
  • @user4581301 指针运算是合法的。将一个对象的指针加一是很好的定义,就好像它是一个长度为 1 的数组一样,并且可以使用结果,就好像它是一个超出假设数组末尾的指针。间接性是可疑的,但 也许 OK。上次我读到,围绕此事的法律术语很模糊,但据我了解,其意图是使其合法。
  • @user4581301 关于指针运算:虽然 +1 是可以的,但实际上在技术上可能确实是 UB 来执行减法指针运算,因为它们不在同一个数组中。但这可能属于 UB 类,没有理智的编译器会破坏,因为它会阻止例如在标准 C++ 中实现 std::vector
  • 这就是我要使用的示例。计算完整的std::vector 的长度。即使他们的正式措辞有点摇摆不定,也表明意图。
【解决方案2】:

&arr 和 arr 是不同的指针。 arr 是数组“arr”的第一个元素的地址。 但是 &arr 是指针 arr 的地址。 &arr 地址中有数组“arr”的地址。 所以它是数组地址的地址。 因此, &arr 是不可预料的,*(&arr + 1) 也是不可预料的。 因为我们不知道&arr的下一个地址保存的是哪个值。

让我解释一下你的两个 printf 语句。 &arr + 1 - &arr 总是返回 1。因为它对 &arr 加一并再次减去 &arr,所以结果为 1。 *(&arr + 1) - arr 返回意外的结果。因为 *(&arr + 1) 是非预期的,而 arr 也是非预期的,所以结果也是非预期的。

这就是这两个结果不同的原因。

抱歉,回答不是用户友好的。 谢谢,最好的问候。

锦衣。

【讨论】:

  • “因为我们不知道 &arr 的下一个地址中保存的是哪个值。” -- 我们不必知道那里保存的是什么。如上所述,您只关心地址,而不是该地址的内容
猜你喜欢
  • 2011-05-01
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
相关资源
最近更新 更多