Reputation: 303
If we have for example f and g defined as:
void f(const int *restrict a, const int *restrict b, int *c){ ... }
void g(const int * a, const int * b, int *c){ ... }
If restrict
is redundant I would expect all three answers to be yes.
Otherwise, why not?
Do not take into account bad programming practices like casting away the const
qualifier.
Upvotes: 17
Views: 685
Reputation: 141586
For this case:
void f(const int *restrict a, const int *restrict b, int *c)
restrict
is not redundant. It means the compiler can assume that a
and c
do not alias. For example if the function body were:
int d = *a;
*c = 5;
d = *a;
then the compiler could remove the third line.
This is covered by C11 6.7.3/7:
This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.
which is saying that if an object is accessed through a
, then the object is not allowed to also be accessed via b
or c
.
The formal definition can be seen in C11 6.7.3.1/4 (Formal definition of restrict):
If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified
Here T is the declared type pointed to by a
, i.e. const int
, and L is *a
, and X is whatever int
that a
and c
are pointing to.
Upvotes: 4
Reputation: 16156
Has the compiler the same optimization opportunities?
If I understand the standard correctly, then the compiler has greater optimization opportunities with the version with restrict
qualified pointers:
During each execution of
B
[some block of code], letL
be any lvalue that has&L
based onP
[the restrict qualified pointer]. IfL
is used to access the value of the objectX
that it designates, andX
is also modified (by any means), then the following requirements apply:T
[the typeP
points to] shall not be const-qualified. [..][N1570 §6.7.3.1/4, emphasis mine]
Logically speaking, if the object is modified, then the pointer to it shall not be const-qualified. Thus, if the pointer is const-qualified, the object may not be modified (by any means).
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
Thus, if the compiler sees T const * restrict
, then it can be sure that the object "behind" that pointer cannot be modified during the lifetime of that pointer. As such ...
Assumming f and g have equivalent bodies, are they the same from the caller point of view?
... this is a much stronger guarantee for the caller than just using T const *
.
Upvotes: 0
Reputation: 8956
Do not take into account bad programming practices like casting away the const qualifier.
The problem is that even in standard C the presence of const
on a pointer is not a binding contract. It is merely a suggestion to the programmer that the callee won't attempt to modify the pointee. The code is in fact permitted to modify the pointee (after casting) as long as the pointee was not originally declared as a const
object.
Therefore, compilers are not able to use const
safely: they still need to examine the contents of the callee to make sure that it isn't lying, if even possible.
Upvotes: 3