对于restrict指针p,Based-On的定义意味着若令int* n = p,&*n并非以p 为基准
《C99标准草案n1256》在6.7.3.1p3、6.7.3.1p4中关于restrict限定指针的描述如下:
3在下文中,当且仅当一个指针表达式
E基于对象P时成立,如果在对B的执行过程中的某个序列点,且在对E进行评估之前,对P进行修改,使其指向其原来所指向的数组对象的副本,将改变E的值。注意,“based” 这个词只对指针类型表达式有定义4在每次执行
B时,让L成为一个具有基于P的&L的左值。如果L被用于访问它所指示的对象X的值,且X也被修改(以任何方式),则下列要求适用:T不能有const限定。用于访问X的值的其他所有左值的地址也应以P为基址。任何修改X的访问在本小条的目的下也应被视为同时修改P。
出于方便起见,下面复制了一个对 another post 所示程序进行轻微修改(仅变量名改名)的版本。
int main(void){
int x = 5;
int* restrict p;
p = &x;
*p = 10;
//*p is an lvalue where &*p is based on p
//x is modified so semantics of 6.7.3.1p4 apply
int* n = p;
*n = 20;
//&*n is not based on p, since if p were to change prior to *n,
//the value of &*n would not change
//hence this access is not valid
}
我写了注释,解释为什么我认为 *n = 20; 违反了restrict qualified pointers的规则。据我理解,在 n 的声明之后就有一个序列点。*n 是用来访问由 x 指定的对象的左值。如果在这一序列点将 p 改为指向 x 的一个副本,那么 &*n 的左值的地址将不会改变。因此 &*n 并非基于 p,所以这次访问违反了restrict qualified pointers的规则。
然而,对这篇帖子的另一位发言人gnasher729的评论是这样说的:
In this case you have no undefined behaviour because
nis based onp. If you wroten = &xthennwouldn’t be based onpleading to undefined behaviour.
这与我对restrict qualified pointers的理解相矛盾,我感到困惑。请问有人能解释在上面的程序中,为什么 &*n 不是基于 p,我的推理哪里出错?
此贴并非与 另一个帖子 重复,因为该帖子并未要求澄清/纠正我对restrict指针的理解,也没有提供任何帮助来澄清/纠正我的理解。比如,它没有解释为什么 &*N 基于 P,以及我的推理为什么是错的。
解决方案
n 和 &*n 基于 p。在初始赋值之后、在 int* n = p; 之前修改 p,将会改变 n,这属于可用的块 B。
条件“在 某个 序列点…”若存在一个序列点能使剩余条件成立,则该条件成立。存在其他序列点并不满足该条件的事实并不相关;该条件并不要求在每一个序列点都成立。