如果我们将f和g定义为:
void f(const int *restrict a, const int *restrict b, int *c){ ... }
void g(const int * a, const int * b, int *c){ ... }
如果restrict
多余,我希望所有三个答案都是肯定的
否则,为什么不呢?
不要考虑糟糕的编程习惯,例如丢弃const
限定符。
答案 0 :(得分:4)
对于这种情况:
void f(const int *restrict a, const int *restrict b, int *c)
restrict
并非多余。这意味着编译器可以假定a
和c
不是别名。例如,如果函数体是:
int d = *a;
*c = 5;
d = *a;
然后编译器可以删除第三行。
C11 6.7.3 / 7涵盖了这一点:
此关联在下面的6.7.3.1中定义,要求所有访问 该对象直接或间接使用该特定指针的值。
表示如果通过a
访问对象,则不允许通过b
或c
访问该对象。
正式定义见C11 6.7.3.1/4(限制的正式定义):
如果 L 用于访问其指定的对象 X 的值,则 X 也会被修改(无论如何) ,则以下要求适用: T 不得为const限定
此处 T 是a
指向的声明类型,即const int
, L 是*a
,< strong> X 是int
和a
所指向的c
。
答案 1 :(得分:3)
不要考虑糟糕的编程习惯,比如抛弃const限定符。
问题是即使在标准C中,指针上const
的存在也不是绑定合同。程序员只是建议被调用者不会尝试修改指针。事实上,只要指针对象最初没有被声明为const
对象,就允许代码修改指针对象(在转换之后)。
因此,编译器无法安全地使用const
:他们仍然需要检查被调用者的内容,以确保它没有说谎,如果可能的话。
答案 2 :(得分:0)
编译器是否有相同的优化机会?
如果我正确理解the standard,那么编译器对具有restrict
限定指针的版本有更大的优化机会:
在每次执行
B
[某段代码]时,让L
为基于&L
[限定限定指针]P
的左值。如果L
用于访问其指定的对象X
的值,并且X
也被修改(无论如何), 然后,以下要求适用:T
[类型P
指向]不应符合限定条件。 [..][N1570§6.7.3.1/ 4,强调我的]
从逻辑上讲,如果对象被修改,那么指向它的指针不应该是const限定的。因此,如果指针是 const-qualified,则不能修改该对象(无论如何)。
Xmodified Tconst !Tconst Xmodified -> !Tconst
true true false false // oops, must disallow this case
true false true true
false true false true
false false true true
因此,如果编译器看到T const * restrict
,那么可以确定在该指针的生命周期内不能修改该指针的“后面”对象。就这样......
假设f和g具有等效的主体,从呼叫者的角度来看它们是否相同?
...这比调用者更有力,而不仅仅是使用T const *
。