【问题标题】:Why is a[j] equal to j[a] for every array a and integer j? [duplicate]为什么对于每个数组 a 和整数 j,a[j] 等于 j[a]? [复制]
【发布时间】:2019-10-18 01:16:05
【问题描述】:

我正在阅读“C++ 编程语言”中关于指针和数组的部分,我遇到了一些让我难过的东西。

对于a范围内的每个内置数组a和整数j,我们 有:

a[j] == *(&a[0]+j) == *(a+j) == *(j+a) == j[a]

我明白为什么*(&a[0]+j)a[j] 的含义相同,因为&a[0] 指向a 的第一个元素,然后它增加了j

我还知道*(a+j)*(j+a) 等于a[j],a 从数组隐式转换为指向 a 的第一个元素的指针,然后递增 j 并取消引用。

但为什么是a[j] == j[a]? 我错过了什么?

【问题讨论】:

  • a[b] 被定义为等同于*(a + b),和+ commutes。
  • a[j]*(a+j) 的语法糖。 j[a]*(j+a) 的语法糖。并且*(j+a)*(a+j) 相同。
  • 有趣的问题。我认为这会让许多经验丰富的编码人员感到惊讶,尽管这很明显。

标签: c++ arrays c++11 pointers


【解决方案1】:

因为下标运算符是可交换的。它只是由语言指定的。

你可以从指针算术表达式的等价中看出对称性,其中加法运算符也是可交换的:

a[j] == ∗(a+j)
j[a] == ∗(j+a)
∗(a+j) == ∗(j+a)

语言标准(草案)说:

[expr.sub]

...表达式 E1[E2] 与 *((E1)+(E2)) 相同(根据定义)...

[注意:尽管它的外观不对称,但下标是一种交换操作,除了排序。

【讨论】:

  • 谢谢,这就解释了。如果没有将j[a] ==∗(j+a) == *(a+j)a[j] 也等于这一事实联系起来,我感到相当愚蠢。
  • 如果 a[j] == j[a],a[j] 会产生与 j[a] 相同的汇编代码吗?我有种不会的感觉。在 IA32 上,假设 EBX 有 a[0] 的地址(即 EBX = &a[0],ESI 的值为 j。此外,我们假设 a 是一个 32 位整数数组,所以 a[j ] 转换为 [EBX+4*ESI] 但 j[a] 将转换为 [ESI+4*EBX]。EBX+4*ESI 很可能与 ESI+4*EBX 的值不同
  • @mcleod_ideafix 没有理由将表达式转换为您建议的指令。例如,请参阅如何将两个表达式转换为相同的指令:godbolt.org/z/aNsv25
  • 我明白了。无论您如何编写 [] 表达式,编译器都可以检测到哪一个是实际指针,哪一个是实际偏移量,因此在这两种情况下都会发出相同的操作码。
猜你喜欢
  • 1970-01-01
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2019-04-19
  • 2021-11-11
  • 2021-11-01
  • 2021-11-03
相关资源
最近更新 更多