为什么 * 需要放在 (&a) 之前来减去 a(a 是一个数组)?

Dat*_* Le 9 c++ pointers

我正在学习如何找到数组的长度,但我对这个解决方案感到困惑。我试图在网上找到解释,但似乎没有。

int arr[5] = {5, 8, 1, 3, 6};
   int len = *(&arr + 1) - arr;
   cout << "The length of the array is: " << len;
Run Code Online (Sandbox Code Playgroud)

Mig*_*uel 7

数组的内存地址与第一个元素的内存地址相同,当你对一个指针进行加减运算时,是由它所指向的类型的大小来完成的,所以:

  • arrint&arrint[5]
  • &arr+1 以五个整数的大小递增内存地址。
  • 如果你这样做,(&arr+1)-arr你会得到一个编译错误,因为它们是不同的类型。
  • 如果你这样做,(&arr+1)-&arr你会得到1,因为内存地址的偏移量与int[5].
  • 因此,当您这样做时*(&arr+1),您将获得相同的内存地址,但指向int而不是int[5]。现在你不会得到编译错误,因为两个指针都指向int并且你得到内存地址的int大小偏移量,而不是int[5]. 内存地址和类型有时很难解释,希望我说清楚。在这里,您可以运行一些代码来查看提到的一些概念:
   int arr[5] = {5, 8, 1, 3, 6};
   int len = *(&arr + 1) - arr;
   
   cout << "arr: " << arr << endl;
   cout << "arr + 1: " << arr+1 << endl;
   cout << "&arr: " << &arr << endl;
   cout << "&arr + 1: " << &arr+1 << endl;
   cout << "*(&arr + 1): " << *(&arr+1) << endl;
   
   // cout << "&arr + 1 - arr: " << &arr+1-arr << endl;
   // error: invalid operands of types ‘int (*)[5]’ and ‘int [5]’ to binary ‘operator-’

   cout << "The length of the array is: " << len;
Run Code Online (Sandbox Code Playgroud)


S.M*_*.M. 6

数组的类型arrint[5],类型&arrint(*)[5](&arr + 1)增加数组地址,sizeof(int[5])因为它是由指针算法的规则完成的,即计算数组之后的地址。*(&arr + 1)int[5],紧跟在 之后的数组arr,该arr[5]放在哪里。减法的两个参数都衰减到int*。减去指向 int 的指针得到 5。

这可以被认为是未定义的行为,因为属于不同对象存储的指针的减法没有定义。带有指向未分配内存的指针(如(&arr + 1))的表达式的结果也是未定义的。

  • 我相信这是一个已知的语言缺陷,即这是否是 UB 是不明确的。我不久前问过一个类似的问题:[取消引用数组类型的结束指针](/sf/ask/3690893181/)。 (6认同)