为什么 C 数组的 5[a] 没有超出范围?

Why 5[a] with C arrays isn't out of range?

根据 Post: With arrays, why is it the case that a[5] == 5[a]?

声称 a[5] 等于 5[a]

我在问自己,这是真的吗?

虽然我同意 E1[E2] 等同于 (*((E1)+(E2)))

但我要声明:鉴于

的声明
int a[sizeI];

其中 if (sizeI > 5) 必须是 true

我同意 a[5] 没问题。

但与引用自 ISO/IEC:9899

相关

附录 J.2 未定义的行为:

— An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6).

是(如果我从文档中得到正确的话)5[a] "apparently accessible" 但是 "array subscript is out of range" 所以我总体上不同意我链接的 OP, 因为 a[5] 在给定的情况下定义明确,而 5[a] 是未定义的行为。

那么,我说得对吗?还是我忘了考虑一些重要的事情?

编辑:

我的说法并不意味着

E1[E2] is identical to (*((E1)+(E2)))

不正确。

还有6.5.2.1数组下标点2

只是说它们在算术上是相同的。 但没有什么是这样说的:(*((E1)+(E2))) can't achieve UB.

所以虽然我知道这一部分,但我找不到任何破坏我的主张的东西

另请注意:

正如你在我的第一句话中应该看到的那样, 我问的是与

所述的 "problem" 相关的不同问题

With arrays, why is it the case that a[5] == 5[a]?

所以请停止将其标记为与那个重复。

我认为这是真的。可能没关系,因为它进行相同的计算:

 *(arr + 4) // For the arr[4]
 *(4 + arr) // For the 4[arr]

结论相同。

#include <stdio.h>

int main(void)
{
    int arr[5] = {1,2,3,4,5};
    printf("\n%d %d\n", arr[4], 4[arr]);
    printf("\n%d %d\n", arr[5], 5[arr]);
    printf("\n%d %d\n\n", arr[6], 6[arr]);

    return 0;
}

在每个 printf 中,行为都符合预期。

要了解为什么附录 J.2 中的注释兼容 a[b]*(a + b) 相同,请考虑如何解释像 a[1][7] 这样的表达式(假设声明 int a[4][5],如附录):

a[1][7] 等同于 *(a[1] + 7)。数组 a 的每个元素都是一个五元素数组,因此 a[1] 计算为指向五元素数组第一个元素的指针。如果您将 7 添加到这样的指针,那么生成的指针将指向五元素数组之外,这意味着您不能取消引用它(标准方面 - 它可能在实践中起作用)。但这正是上述表达式的作用。

顺便说一下,附录 J.2 中的注释与 a[5]5[a] 无关。如果数组至少有六个元素,那么在这两个表达式中调用元素 "apparently accessible" 是合理的。他们只是想澄清,您不允许访问索引的 any 中溢出的多维数组,即使它看起来不应该溢出边界多维数组。这只是一个注释——你可以独立地推导出它(如上所述)。

5不是数组,所以5[a]不是数组下标

无论哪种方式,附件 J 都是 信息性的 这意味着它是为了提供额外的帮助,而不是作为规范的一部分。所以我们不能仅仅根据 J.2 所说的就对未定义的行为做出任何声明。

关于指针运算的规范部分是6.3.2.3,其中包括5[a]a[5]相同的证明。