像这样的代码有很多:
#include <stdio.h>
int main(void)
{
int a[2][2] = {{0, 1}, {2, -1}};
int *p = &a[0][0];
while (*p != -1) {
printf("%d\n", *p);
p++;
}
return 0;
}
但是基于这个answer , 行为未定义。
N1570。 6.5.6 p8:
When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.
谁能详细解释一下?
最佳答案
基地址(指向第一个元素的指针)p
被赋值的数组是int[2]
类型。这意味着 p
中的地址只能在位置 *p
和 *(p+1)
处合法地取消引用 ,或者如果您更喜欢下标表示法,p[0]
和 p[1]
。此外,p+2
保证是合法评估的地址,并且可与该序列中的其他地址,但不被解除引用。这是过去地址。
您发布的代码通过取消引用 p
违反了一次过去的规则,一旦它传递了它所在数组中的最后一个元素。它所在的阵列支撑在另一个类似尺寸的阵列上,这与引用的正式定义无关。
也就是说,在实践中它是有效的,但正如人们常说的那样。 观察到的行为不是,也不应被视为定义的行为。仅仅因为它有效并不能说明它是正确的。
关于c - 使用单个指针访问二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25303647/