据我了解,section 6.7.3.1 of the C standard中“限制”的正式定义是,在下面的函数中,指针y
基于restrict
指针x
;因此,编译器将假定访问*x
和*y
可能是别名:
void assign1(int *pA, long N) {
int *restrict x = pA;
{
int *y = x + N;
*x = *y;
}
}
但是,如果将y
本身声明为restrict
,怎么办:编译器可以假定*x
和*y
永远不会别名吗?
void assign2(int *pA, long N) {
int *restrict x = pA;
{
int *restrict y = x + N;
*x = *y;
}
}
[Quoting Jeroen Dobbelaere,从事“限制”实现的LLVM开发人员:
这在6.7.3.1 paragraph 4中定义:
...用于访问X值的所有其他左值也应具有基于P的地址...
对于assign1
:
x
是一个限制指针,并假定指向它自己的对象集]y
是普通指针,基于x
x
指向的对象集的所有访问都是通过基于x
的指针完成的>对于assign2
:
x
是一个限制指针,并假定指向它自己的对象集]y
也是基于x
的限制指针,但是在y
的范围内,假定指向它自己的对象集>*x
和*y
绝不能重叠,因为对y
对象的所有访问都必须基于从y
派生的指针进行这样,N = 0将触发assign2
中未定义的行为>
对内部块外部的*x
进行赋值,使代码再次有效:
void assign3(int *pA, long N) {
int *restrict x = pA;
int tmp;
{
int *restrict y = x + N;
tmp = *y;
}
*x = tmp; // may alias with *y
}