为什么 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]
相同的证明。
根据 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 inta[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]
相同的证明。