像这样的代码有很多:
#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 https://stackoverflow.com/a/7785116/1606345,行为未定义。
N1570。 6.5.6 p8:
当对整数类型的表达式进行加法或减法时
对于指针,结果具有指针操作数的类型。如果
指针操作数指向数组对象的元素,并且数组
足够大,结果指向与
原始元素使得下标的差异
结果和原始数组元素等于整数表达式。
换句话说,如果表达式 P 指向 an 的第 i 个元素
数组对象,表达式 (P)+N(相当于 N+(P))和 (P)-N
(其中 N 的值为 n)分别指向第 i+n 和
数组对象的第 i−n 个元素(前提是它们存在)。而且,
如果表达式 P 指向数组对象的最后一个元素,则
表达式 (P)+1 指向数组对象的最后一个元素,
如果表达式 Q 指向数组的最后一个元素
对象,表达式 (Q)-1 指向数组的最后一个元素
目的。如果指针操作数和结果都指向元素
同一数组对象,或数组的最后一个元素
对象,评估不得产生溢出;否则,
行为未定义。如果结果指向最后一个元素
数组对象的,它不应该被用作一元的操作数
* 被评估的运算符。
有人可以详细解释一下吗?
数组的基地址(指向第一个元素的指针)p
被分配的类型int[2]
。这意味着地址在p
可以合法地解引用的仅在地点*p
and *(p+1)
,或者如果您更喜欢下标表示法,p[0]
and p[1]
。此外,p+2
保证是合法的评价的作为地址,并且可比到该序列中的其他地址,但可以not被解除引用。这是过去的地址。
您发布的代码通过取消引用违反了过去的规则p
一旦它传递了它所在数组中的最后一个元素。它所在的数组被另一个相似维度的数组支撑,这与引用的正式定义无关。
也就是说,在practice它有效,但正如人们常说的那样。observed行为不是,也不应该被考虑,定义的行为。仅仅因为它有效并不意味着它就是正确的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)