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

Nor*_*wap 16 c pointers restrict restrict-qualifier

首先是一些参考.在C99标准说,这大约restrict在第6.7.3:

通过限制限定指针访问的对象与该指针具有特殊关联.此关联在下面的6.7.3.1中定义,要求对该对象的所有访问都直接或间接使用该特定指针的值.117)restrict限定符(如register存储类)的预期用途是促进优化,并且从构成符合程序的所有预处理转换单元中删除限定符的所有实例不会改变其含义(即,可观察行为).

然后(§6.7.3.1"正式定义restrict"):

D是提供指定的对象的装置的一个普通标识符的声明P作为限制限定指针输入T.

如果D出现在块内并且没有存储类extern,则B表示该块.如果D出现在函数定义的参数声明列表中,则B表示关联的块.否则,让我们B表示main块(或在独立环境中在程序启动时调用的任何函数块).

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

在每次执行期间B,L设为任何&L基于的 左值P.如果L用于访问X它指定的对象的值,并且X也被修改(通过任何方式),则以下要求适用:T不应该是const限定的.用于访问值的每个其他左值X也应该具有基于的地址P.出于本子条款的目的,每次修改的访问也X应被视为修改P.如果P指定了一个指针表达式的值,该指针表达式E基于P2与块相关联的另一个受限指针对象,B2那么执行B2 应该在执行之前开始B,或者执行B2应该在赋值之前结束.如果不满足这些要求,则行为未定义.

正如一些人所指出的,这说明了规则(标准中的例子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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

因此,我的第二个问题:从外部到内部(允许)的分配是什么,而不是从内部到外部(禁止,例如p1 = q1;在上面的第一个例子中)?

gna*_*729 -3

这些都不是未定义的行为。您可以根据需要在限制指针之间进行分配。如果以错误的方式分配给限制指针指向的对象,则可能会出现未定义的行为。

在第二个示例中,指针 y 是从 x 派生的,因此首先分配给 *x,然后分配给与 *y 相同的变量,也可以。

与其阅读法律术语,您是否真正思考过“限制”应该实现什么目的?