对 C 限制限定符感到困惑
Confused about C restrict qualifier
首先,cppreference对restrict有如下说法:
During each execution of a block in which a restricted pointer P is declared (typically each execution of a function body in which P is a function parameter), if some object that is accessible through P (directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P (directly or indirectly), otherwise the behavior is undefined.
但是在这一段下面写着:
Restricted pointers can be assigned to unrestricted pointers freely, the optimization opportunities remain in place as long as the compiler is able to analyze the code:
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
) ?
第二个:
Assignment from one restricted pointer to another is undefined behavior, except when assigning from a pointer to an object in some outer block to a pointer in some inner block (including using a restricted pointer argument when calling a function with a restricted pointer parameter) or when returning from a function (and otherwise when the block of the from-pointer ended).
那么,下面的代码可以吗?
void foo(char* restrict a, size_t s)
{
for(char* restrict aa = a; aa < a + s; ++aa) // Is aa in an inner block?
{
*aa = '[=11=]';
}
}
示例 1 的关键是用于访问 r
指向的底层数组的左值 *p
的地址基于 r
。换句话说,它是通过 r
的 间接 访问。由于 *q
也有其基于 s
的地址,因此所有访问均通过原始受限指针发生,即使是间接访问:此处没有 UB。
示例 2 更为简单。您在原始指针上声明了一个新的受限指针 based。所以也没有UB。但是在示例 2 中,两个受限限定符都没有添加任何值,因为在块内部(foo
函数定义)只使用了一个指针,因为 aa
基于 a
.
在示例 1 中,restrict
限定符向编译器声明由 r
和 s
指向的数组不重叠:无法通过 r
访问(直接或间接通过 p
) 应该触及 s
.
指向的数组
首先,cppreference对restrict有如下说法:
During each execution of a block in which a restricted pointer P is declared (typically each execution of a function body in which P is a function parameter), if some object that is accessible through P (directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P (directly or indirectly), otherwise the behavior is undefined.
但是在这一段下面写着:
Restricted pointers can be assigned to unrestricted pointers freely, the optimization opportunities remain in place as long as the compiler is able to analyze the code:
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
) ?
第二个:
Assignment from one restricted pointer to another is undefined behavior, except when assigning from a pointer to an object in some outer block to a pointer in some inner block (including using a restricted pointer argument when calling a function with a restricted pointer parameter) or when returning from a function (and otherwise when the block of the from-pointer ended).
那么,下面的代码可以吗?
void foo(char* restrict a, size_t s)
{
for(char* restrict aa = a; aa < a + s; ++aa) // Is aa in an inner block?
{
*aa = '[=11=]';
}
}
示例 1 的关键是用于访问 r
指向的底层数组的左值 *p
的地址基于 r
。换句话说,它是通过 r
的 间接 访问。由于 *q
也有其基于 s
的地址,因此所有访问均通过原始受限指针发生,即使是间接访问:此处没有 UB。
示例 2 更为简单。您在原始指针上声明了一个新的受限指针 based。所以也没有UB。但是在示例 2 中,两个受限限定符都没有添加任何值,因为在块内部(foo
函数定义)只使用了一个指针,因为 aa
基于 a
.
在示例 1 中,restrict
限定符向编译器声明由 r
和 s
指向的数组不重叠:无法通过 r
访问(直接或间接通过 p
) 应该触及 s
.