C ';限制';关键字-为什么允许从外部限制变量分配到内部限制变量?
首先是一些参考文献。第6.7.3节中关于限制的说明如下: 通过限制限定指针访问的对象具有 与该指针的特殊关联。此关联在中定义 6.7.3.1要求对该对象的所有访问直接或间接使用该特定指针的值。117)预期 使用C ';限制';关键字-为什么允许从外部限制变量分配到内部限制变量?,c,pointers,restrict,restrict-qualifier,C,Pointers,Restrict,Restrict Qualifier,首先是一些参考文献。第6.7.3节中关于限制的说明如下: 通过限制限定指针访问的对象具有 与该指针的特殊关联。此关联在中定义 6.7.3.1要求对该对象的所有访问直接或间接使用该特定指针的值。117)预期 使用限制限定符(如寄存器存储类)是为了 促进优化,并从中删除限定符的所有实例 构成一致性程序的所有预处理翻译单元 不会改变其含义(即,可观察到的行为) 然后(§6.7.3.1“限制的正式定义”): 设D为提供方法的普通标识符的声明 将对象P指定为类型T的限制限定指针 如果D出现在块内,并且没有
限制
限定符(如寄存器
存储类)是为了
促进优化,并从中删除限定符的所有实例
构成一致性程序的所有预处理翻译单元
不会改变其含义(即,可观察到的行为)
然后(§6.7.3.1“限制的正式定义”):
设D
为提供方法的普通标识符的声明
将对象P
指定为类型T
的限制限定指针
如果D
出现在块内,并且没有存储类extern
,
让B
表示块。如果参数列表中出现D
函数定义的声明,让B
表示相关的
块否则,让B
表示main块(或
在程序启动时以独立的方式调用的任何函数
环境)
在下文中,指针表达式E
被称为基于对象p
if
(在
计算E
)修改P
以指向数组对象的副本
它以前指向的将更改E
.119)注释的值
仅为具有指针类型的表达式定义了“基于”
在每次执行B
的过程中,让L
为基于
P
。如果使用L
访问对象X
的值,则
指定,并且还修改了X
(通过任何方式),然后
适用要求:T
不得为合格。其他左值
用于访问X
值的地址也应基于P
。
每个修改X
的访问也应被视为修改P
,例如
本款的目的。如果P
被赋值为
基于另一个受限指针的指针表达式E
对象P2
,与块B2
关联,然后执行B2
应在执行B
之前开始,或应在执行B2
之前开始
在任务之前结束。如果不满足这些要求,则
该行为未定义
如图所示,这说明了规则(标准中的示例4):
现在,我的第一个问题是:为什么可以从外部受限指针分配到内部受限指针
我的理解是,没有任何东西禁止这样做,因为它有明显的别名:
int * restricted x = /* ... */ ;
{
int * restricted y = x;
*x = 3;
printf("%d\n", *y); // 3
*y = 4;
printf("%d\n", *x); // 4
}
当然,别名集仅限于两个指针
因此,我的第二个问题:从外部到内部(允许),但从内部到外部(禁止,例如上文第一个示例中的
p1=q1;
)分配的差异是什么?这些都不是未定义的行为。您可以随意在限制指针之间赋值。如果以错误的方式指定限制指针指向的对象,则可能会发生未定义的行为
在第二个例子中,指针y是从x派生出来的,所以首先赋给*x,然后赋给与*y相同的变量也可以
你有没有想过“限制”应该达到什么目的,而不是阅读法律术语 我认为这些规则旨在满足两个目标:
restrict
中获益restrict
限定符远非完美,但它仍然比大多数替代品要好。请更改它,使其能够真正编译。在函数的参数列表中,不是唯一可以将指针声明为restrict
的地方吗?@fuzzxl不,标准没有这样说,而且它在所有警告和严格的标准遵从性启用的情况下都能很好地工作。restrict
的语义如果描述允许编译器执行的操作比禁止程序员执行的操作更容易理解,但我认为基本思想是restrict
允许编译器的行为,就像任何通过restrict
指针的读取都是在指针赋值和逻辑读取发生点之间的执行序列中的任何位置执行的一样,和写操作允许在指针生命周期内的任何时间发生,超出逻辑写操作发生的位置,除非读和写操作不能发生…如果您有两个函数void foo(int*restrict a,int*
int * restricted x = /* ... */ ;
{
int * restricted y = x;
*x = 3;
printf("%d\n", *y); // 3
*y = 4;
printf("%d\n", *x); // 4
}