指针算法 - 编译器如何确定要递增的字节数?

Pointer arithmetic - how does the compiler determine the number of bytes to increment?

考虑以下代码。

#include <iostream>

int main(){
  int a[] = {1,2,3,4,5};
  int b = 5;
  std::cout << a[b] << std::endl;
  std::cout << b[a] << std::endl;
}

我理解 a[b]b[a] 是相同的,正如标准所规定的那样:

Except where it has been declared for a class (13.5.5), the subscript operator [] is interpreted in such a way that E1[E2] is identical to *((E1)+(E2)). Because of the conversion rules that apply to +, if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th member of E1. Therefore, despite its asymmetric appearance, subscripting is a commutative operation.

不过,我还是不太明白。编译器确实以字节为单位进行寻址运算。由于一个int占用4个字节,所以a[b]b[a]都会被翻译成*(a + b * 4)。我的问题是:编译器如何确定正确的翻译是 *(a + b * 4),而不是 *(b + a * 4)?当编译器得到 E1[E2] 形式的表达式时,编译器可以将其翻译成 *(E1 + E2 * 4)*(E2 + E1 * 4) - 编译器如何知道哪个是正确的选择?

决定因素类型不是对象的大小。它是对象的实际、完整类型。

编译器知道每个对象的实际类型。编译器不仅知道 a 是四个字节(或者在 64 位系统上是八个字节),而且它是一个指针并且 b 是一个整数类型。这是 C++ 的一个基本方面:每个对象的类型在编译时是并且必须是已知的。

因此,当将指针类型添加到整数类型时,整数值会乘以所指向类型的大小。哪个在 + 运算符的左侧和右侧并不重要。如果一个操作数是指针,而另一个是整数类型,这就是 C++ 中发生的情况。

想象一种 C±± 语言,它就像 C++,只是它没有任何数组索引的概念,也没有下标 operator []。不过,所有其他 C++ 规则和定义仍然适用。

Except where it has been declared for a class (13.5.5), the subscript operator [] is interpreted in such a way that E1[E2] is identical to *((E1)+(E2)).

这里C++标准所说的可以粗略地理解为:C++编译器首先将所有下标表达式E1[E2]翻译成*((E1)+(E2))。结果是有效的C±±码, 然后根据C±±规则进一步评估。

这意味着 a[b]b[a] 分别转换为 *(a + b)*(b + a),它们是相同的,因为加法在 C++ 中是可交换的(因此 C± ±).