首先,cppreference有关于restrict的以下内容:
在每次执行声明受限指针P的块(通常每次执行P是函数参数的函数体)时,如果某个可通过P(直接或间接)访问的对象被修改,无论如何,那个块中对该对象的所有访问(包括读取和写入)都必须通过P(直接或间接)进行,否则行为是未定义的。
但是在这一段之下它说:
可以自由地将受限制的指针分配给不受限制的指针,只要编译器能够分析代码,优化机会就会保留到位:
void f(int n, float * restrict r, float * restrict s) {
float * p = r, * q = s; // OK
while(n-- > 0) *p++ = *q++; // almost certainly optimized just like *r++ = *s++
}
在上面,r[0]
是一个可以通过限制指针r
访问的对象,它可以通过p
访问,这似乎与第一段(访问r[0]
必须仅通过r
)生效?
第二
从一个受限指针到另一个受限指针的赋值是未定义的行为,除非从指向某个外部块中的对象的指针指向某个内部块中的指针(包括在使用受限指针参数调用函数时使用受限指针参数) )或从函数返回时(否则当从指针的块结束时)。
那么,以下代码是否正常?
void foo(char* restrict a, size_t s)
{
for(char* restrict aa = a; aa < a + s; ++aa) // Is aa in an inner block?
{
*aa = '\0';
}
}
答案 0 :(得分:2)
示例1中的关键是,用于访问transform : translateX(n%)
指向的基础数组的左值*p
的地址基于r
。换句话说,它是通过r
进行的间接访问。由于r
的地址也基于*q
,所有访问都会通过原始的限制指针间接发生:这里没有UB。
示例2更加微不足道。您在原始指针上声明了一个新的受限指针基于。所以也没有UB。但是在示例2中,两个受限限定符都没有添加任何值,因为在块内(s
函数定义)只使用了一个单指针,因为foo
基于aa
。
在示例1中,a
限定符向编译器声明restrict
和r
指向的数组不重叠:无法通过s
(直接或间接访问)通过r
)应触及p
指向的数组。