我在C11标准中提到了restrict
限定词的这两个部分:
1#
6.7.3-8
通过限制限定指针访问的对象具有 与该指针的特殊关联。这种关联,定义于 下面的6.7.3.1要求对该对象的所有访问直接或间接使用该特定指针的值.135)预期的 使用restrict限定符(如寄存器存储类)是 促进优化,并删除限定符的所有实例 来自构成符合的所有预处理翻译单元 程序不会改变其含义(即可观察的行为)。
你能解释一下草书片段的含义吗?在我的解释中,由于它没有改变它的含义,看起来使用restrict
只是毫无意义......
2#
6.7.3.1-6
翻译人员可以自由地忽略任何或所有别名含义 使用限制。
这些混叠含义可能是什么?你能告诉我一些例子吗?
答案 0 :(得分:8)
限制并非没有意义,它允许编译器进行优化,否则如果可能存在指针别名则不允许。例如,以下函数:
int foo(int *a, int *b)
{
*a = 5;
*b = 6;
return (*a + *b);
}
此功能返回什么?如果您说11
,那么您只是部分正确。除非11
,否则返回a == b
,在这种情况下,它会返回12
,或者更糟糕的是,它会与b重叠,这可能是多个值之一。为了确保它的行为正确,编译器必须发出
1) stores 5 to a
2) stores 6 to b
3) loads a into a temporary register
4) adds the temp and 6
5) returns the sum
如果您作为程序员知道a == b
永远不会发生,您可以告诉编译器您不希望它使用restrict关键字来担心这种情况。
int foo(int * restrict a, int * restrict b)
将为此功能生成的代码为:
1) store 5 to a
2) store 6 to b
3) return 11
编译器能够进行优化,因为你承诺它不存在别名问题。并且,根据标准,如果编译器只是选择忽略restrict关键字,它将生成的代码将只是第一种情况下的符合(未优化)代码,对于您关心的所有实例仍然会以相同的方式工作。
答案 1 :(得分:6)
第一句话中的草书声明基本上说:
#define restrict
行而不更改c代码的任何含义来定义restrict关键字。由于错过了优化,您的代码可能会变得有点慢,但在所有情况下,您都会获得相同的确定性结果,就像您使用restrict关键字一样。第二段意味着编译器可以自由地忽略restrict关键字。很简单。
答案 2 :(得分:2)
两段都说“限制”只是优化的暗示,实施可以随意忽略它。
答案 3 :(得分:2)
并从构成符合程序的所有预处理翻译单元中删除限定符的所有实例不会改变其含义(即可观察行为)。
这意味着在一致性程序中,restrict
关键字的所有使用都遵循规则,因此删除它不会改变程序的结果。
具体而言,在一致性程序中没有作为restrict
指针传递的参数将别名为其他restrict
指针。否则,删除关键字可能会改变程序的含义。