You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何*(&arr + 1) - arr能准确计算数组元素个数?&arr的指向作用解析

为什么*(&arr + 1) - arr能算出数组的元素个数?

先看一下你给出的代码:

#include <bits/stdc++.h>
using namespace std;
int main() {
    int arr[] = {1, 2, 3, 4, 5, 6};
    int size = *(&arr + 1) - arr;
    cout << "Number of elements in arr[] is " << size;
    return 0;
}

这个技巧的核心在于理解C++中数组名和数组指针的区别,咱们一步步拆解开看:

1. 先搞懂&arr到底是什么

平时我们用数组名arr的时候,它大多会自动退化成指向数组第一个元素的指针(类型是int*),但当你给arr取地址&arr时,规则就变了:

  • &arr的类型是int (*)[6]——翻译成人话就是"一个指向包含6个int的数组的指针",它指向的是整个数组的起始位置,而不是单个元素。
  • 这个指针的"步长"很关键:指针做加法时,偏移量是它指向类型的大小。所以&arr加1的话,会直接跳过整个数组的大小(也就是6 * sizeof(int)字节),而不是只跳一个int。

2. 分析&arr + 1的指向

&arr指向原数组arr的开头,执行&arr + 1后:

  • 指针会偏移整个数组的内存大小,最终指向的是原数组紧挨着的下一个位置——你可以把它想象成一个和arr一模一样的"虚拟数组"的开头,而这个位置刚好就是原数组最后一个元素(arr[5])的下一个内存地址,和arr + 6指向的地方完全一致。

3. 解引用*(&arr + 1)的作用

&arr + 1解引用得到*(&arr + 1),此时这个表达式的结果是那个虚拟数组的数组名,而数组名又会自动退化成指向它第一个元素的指针:

  • 这个指针的类型是int*,指向的就是原数组末尾之后的那个地址(虽然原数组没有arr[6]这个元素,但C++允许指向数组末尾之后的第一个位置,这是合法的)。

4. 指针相减得到元素个数

C++里有个规则:如果两个同类型的指针指向同一个数组(或者数组末尾之后的第一个合法位置),它们相减的结果是两个指针之间的元素个数,而不是字节数。

  • arr退化为指向第一个元素的int**(&arr + 1)退化为指向原数组末尾之后的int*,两者相减就直接得到了数组的元素个数6

举个更直观的例子:假设sizeof(int)是4字节,原数组arr占用的内存是0x1000x117(总共24字节):

  • &arr的值是0x100(类型是数组指针)
  • &arr + 1的值是0x100 + 24 = 0x118
  • *(&arr +1)退化为0x118int*指针
  • arr退化为0x100int*指针
  • 相减计算:(0x118 - 0x100)/4 = 24/4 = 6,正好是元素个数。

小提醒:这个方法只对编译期大小确定的静态数组有效,如果是new int[6]这种动态分配的数组,arr本质是int*&arr就是指向指针的指针,这个技巧就用不了了。

内容的提问来源于stack exchange,提问作者Anujeet Kunturkar

火山引擎 最新活动