'restrict'关键字 - 为什么允许从外部受限变量赋值给内部受限变量?

时间:2015-03-26 10:32:10

标签: c pointers restrict restrict-qualifier

首先参考一些。 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表示主要块(或块)   在独立的程序启动时调用的任何函数   环境)。

     

在下文中,指针表达式E在对象P上被称为基于   (在B执行之前的某个序列点   评估E)修改P以指向数组对象的副本   它以前指出的将改变E的值。 119)注意   ''based''仅针对具有指针类型的表达式定义。

     

在每次执行B期间,让L为基于&L P的任何左值   L。如果X用于访问对象X的值   指定,T也被修改(以任何方式),然后是以下内容   要求适用:X不得为const限定。每个其他左值   用于访问P的值的地址也应基于X。   修改P的每个访问权限也应被视为修改P   本条款的目的。如果为E分配了a的值   指针表达式P2,它基于另一个受限制的指针   对象B2,与块B2关联,然后执行B   应在执行B2之前开始,或执行{ 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 } }   在转让之前结束。如果不满足这些要求,那么   行为未定义。

作为some have pointed out,这说明了规则(标准中的示例4):

int * restricted x = /* ... */ ;

{
    int * restricted y = x;
    *x = 3;
    printf("%d\n", *y); // 3
    *y = 4;
    printf("%d\n", *x); // 4
}

现在,我的第一个问题是这样的:为什么可以从外部限制指针分配到内部指针?

我的理解是没有任何禁止这个,它有明显的别名:

p1 = q1;

当然,这组别名仅限于两个指针。

因此我的第二个问题:从外部到内部(允许)分配的区别是什么,但不是从内部到外部(禁止,例如上面第一个示例中的{{1}})?

2 个答案:

答案 0 :(得分:1)

我认为这些规则旨在满足两个目标:

  1. 允许创建一个类似于将参数传递给函数调用时自然创建的临时指针,而不要求使用指针的代码移动到物理上独立的函数中。

  2. 确保显示指针派生的图形没有周期(意味着如果指针x是从y派生的,或者是直接或间接派生自y的任何内容,则y不能从x派生,也不能直接派生或间接衍生自x)。虽然规则可能比实现#2绝对必要的规则更严格,但几乎所有满足第二个要求的有用情况也满足所写的规则,并且编译器很难从restrict中获得很多好处。没有的案例。

  3. restrict限定词远非完美,但它仍然比大多数替代品更好。

答案 1 :(得分:-4)

这些都不是未定义的行为。你可以在所有你喜欢的限制指针之间进行分配。如果以错误的方式分配限制指针指向的对象,则可能会出现未定义的行为。

在你的第二个例子中,指针y是从x派生的,所以首先分配给* x,然后分配给* y的同一个变量,也可以。

你没有阅读法律术语,你真的想过应该达到什么样的“限制”吗?