首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >*(&arr + 1) - arr如何给出数组arr元素的长度?

*(&arr + 1) - arr如何给出数组arr元素的长度?
EN

Stack Overflow用户
提问于 2020-04-16 04:12:20
回答 4查看 1.9K关注 0票数 8
代码语言:javascript
复制
#include <iostream>
using namespace std;

int main() { 
   int  arr[5] = {5, 8, 1, 3, 6};
   int len = *(&arr + 1) - arr;
   cout << "The length of the array is: " << len;
   return 0;
} 

对于上面的代码,我不太理解这两段代码在做什么:

代码语言:javascript
复制
*(&arr + 1) 

代码语言:javascript
复制
*(&arr)
&arr

有人能解释一下吗?因为当我运行以下两个代码时,我得到了以下相同的输出:

&arr (我认为这指向arr的第一个元素的地址)

然后我不太明白这是做什么的,符号*&arr (即这里的地址)做了什么,因为当我运行它们时,两个输出是相同的

最后,当这里的代码将一个整数1添加到地址上时,到底会发生什么:&arr + 1

EN

回答 4

Stack Overflow用户

发布于 2020-04-16 04:29:35

这是一个雷区,但我会试一试:

  • &arr返回指向int[5]
  • + 1的指针int[5]
  • *(&arr + 1)将结果反引用回int(&)[5]

我不知道这是否会导致未定义的行为,但如果不是,下一步将在两个int[5]衰减为int指针之后执行指针算术,返回两个int指针之间的差,即5.

重写以使其更清晰:

代码语言:javascript
复制
int  arr[5] = {5, 8, 1, 3, 6};

int (*begin_ptr)[5] = &arr + 0;     // begin_ptr is a  int(*)[5]
int (*end_ptr)[5]   = &arr + 1;     // end_ptr is a    int(*)[5]

// Note:
//       begin_ptr + 1        ==  end_ptr
//       end_ptr - begin_ptr  ==  1

int (&begin_ref)[5] = *begin_ptr;   // begin_ref is a  int(&)[5]
int (&end_ref)[5]   = *end_ptr;     // end_ref is a    int(&)[5]   UB here?

auto len = end_ref - begin_ref; // the array references decay into int*
std::cout << "The length of the array is: " << len << '\n'; // 5

我将留下一个问题,如果它是UB或未打开,但在引用的存储被分配之前引用一个对象确实看起来有点可疑。

票数 5
EN

Stack Overflow用户

发布于 2020-04-16 05:38:10

示例:

代码语言:javascript
复制
int  arr[] = {1, 2, 3, 4, 5, 6}; 
int size = *(&arr + 1) - arr; 

在这里,指针算法完成了它的一部分。我们不需要显式地将每个位置转换为字符指针。

指向包含6个元素的数组的&arr ==>指针。有关&arr和arr之间的区别,请参阅此内容

作为指针类型,前面6个整数的(&arr + 1) ==>地址是指向6个整数数组的指针。

*(&arr + 1) ==>地址与(&arr + 1)相同,但指针类型为"int *“。

*(&arr + 1) - arr ==>由于*(&arr + 1)指向arr前面6个整数的地址,所以两个之间的差是6。

票数 1
EN

Stack Overflow用户

发布于 2020-04-16 06:51:47

考虑到以下事实:

  • 当您以整数值X递增/递减指针时,指针的值将以指针所指向的类型的字节数的X倍递增/递减。
  • 当您减去2个相同类型的指针时,结果是它们的保留地址之差除以所指向的类型的字节数。
  • 当您仅通过数组的名称引用数组时,它会衰减为指向数组的第一个元素的指针。

你的arr变量的类型是int[5],即一个由5个int组成的数组。&arr返回一个指向arrint[5]*指针(从技术上讲,它实际上是像int(*)[5]一样编写的,但为了简单起见,这里不用担心这个)。让我们在下面将这个指针称为temp

然后,+ 1temp的值递增1个int[5]元素。换句话说,存储在temp中的地址增加了1 * sizeof(int[5])1 * (sizeof(int) * 5)的字节数。这有效地为你提供了一个指向arr末尾的int[5]*指针(即指向&arr[5])。在该内存地址上没有实际存在的int[5]元素,但是出于指针运算的目的,创建指向它的指针是合法的。

取消引用temp为您提供了对arr末尾的int[5]的引用。当传递给operator-时,该引用会衰减为int*指针。

- arr中,对arr的引用在传递给int*时会衰减为指向arr[0]operator-指针。

因此,给定以下代码:

int len = *(&arr + 1) - arr;

它实际上与以下内容相同:

int len = &arr[5] - &arr[0];

它实际上与以下内容相同:

int len = (<address of arr[5]> - <address of arr[0]>) / sizeof(int);

因此,结果是5。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61237796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档