首先是一些参考资料。C99 Standard在第6.7.3节中提到了关于restrict
的内容:
通过限制限定指针访问的对象具有
与指针的特殊关联。此关联,定义于
下面的6.7.3.1要求对该对象的所有访问都直接或间接使用该特定指针的值。117)预期的
使用restrict
限定符(如register
存储类)是为了
升级优化,并从中删除限定符的所有实例
组成一致程序的所有预处理翻译单元
不会改变其含义(即,可观察的行为)。
然后(§6.7.3.1“正式定义restrict
”):
设D
为提供方法的普通标识符的声明
将对象P
指定为指向类型T
的限制限定指针。
如果D
出现在块中,并且没有存储类extern
,
让B
表示块。如果参数列表中出现D
。
函数定义的声明,让B
表示
封锁。否则,让B
表示main的块(或
在程序启动时调用的任何函数
环境)。
在下面的内容中,指针表达式E
被称为基于对象P
如果
(在
修改B
以指向数组对象副本的求值
它以前指向的位置会改变E
.119)注释的值。
仅为具有指针类型的表达式定义了“基于”。
在每次执行P
时,让E
是基于B
。如果使用L
访问对象的值,则
指定,并且&L
也被修改(通过任何方式),然后
适用要求:P
不应为const-qualified。每一个左值
用于访问L
值的地址也应基于X
。
修改X
的每个访问也应被视为修改T
,因为
本款的目的。如果X
被赋予
基于另一个受限指针的指针表达式
对象,与块关联,然后执行
应在执行P
之前开始,或执行X
应
作业前结束。如果不满足这些要求,那么
该行为未定义。
如some have pointed out所示,这说明了规则(标准的示例4):
{
int * restrict p1;
int * restrict q1;
p1 = q1; // undefined behavior
{
int * restrict p2 = p1; // valid
int * restrict q2 = q1; // valid
p1 = q2; // undefined behavior
p2 = q2; // undefined behavior
}
}
现在,我的第一个问题是:为什么可以从外部受限指针分配给内部受限指针?
我的理解是,没有什么能阻止这一点,因为它有明确的别名:
int * restricted x = /* ... */ ;
{
int * restricted y = x;
*x = 3;
printf("%d\n", *y); // 3
*y = 4;
printf("%d\n", *x); // 4
}
当然,别名集仅限于两个指针。
因此,我的第二个问题是:从外部分配到内部(允许),而不是从内部分配到外部(禁止,例如上面第一个示例中的
P
)有什么区别? 最佳答案
我认为这些规则旨在满足两个目标:
允许创建临时指针,类似于将参数传递给函数调用时自然创建的指针,而不要求使用指针的代码移动到物理上独立的函数中。
确保显示指针派生的图形没有循环(这意味着如果指针x派生自y或任何直接或间接派生自y的对象,则y不能派生自x或任何直接或间接派生自x的对象)。虽然规则可能比实现2所绝对需要的规则更严格,但几乎所有满足第二个要求的有用案例也都满足所编写的规则,而且编译器很难从restrict
中获得更多好处。restrict
限定符远不是完美的,但它仍然比大多数替代品要好。
关于c - 'restrict'关键字-为什么允许从外部限制变量分配给内部限制变量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29276248/