首先是一些参考资料。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/

10-09 05:22