Consider the following code:
void doesnt_modify(const int *);
int foo(int *n) {
*n = 42;
doesnt_modify(n);
return *n;
}
where the definition of doesnt_modify
isn’t visible for the compiler. Thus, it must assume, that doesnt_modify
changes the object n
points to and must read *n
before the return
(the last line cannot be replaced by return 42;
).
Assume, doesnt_modify
doesn’t modify *n
. I thought about the following to allow the optimization:
int foo_r(int *n) {
*n = 42;
{ /* New scope is important, I think. */
const int *restrict n_restr = n;
doesnt_modify(n_restr);
return *n_restr;
}
}
This has the drawback that the caller of doesnt_modify
has to tell the compiler *n
isn’t modified, rather than that the function itself could tell the compiler via its prototype. Simply restrict
-qualifying the parameter to doesnt_modify
in the declaration doesn’t suffice, cf. “Is top-level volatile
or restrict
significant [...]?”.
When compiling with gcc -std=c99 -O3 -S
(or Clang with the same options), all functions are compiled to equivalent assembly, all re-reading the 42
from *n
.
Would a compiler be allowed to do this optimization (replace the last line by
return 42;
) forfoo_r
? If not, is there a (portable, if possible) way to tell the compilerdoesnt_modify
doesn’t modify what its argument points to? Is there a way compilers do understand and make use of?Does any function have UB (provided
doesnt_modify
doesn’t modify its argument’s pointee)?
Why I think, restrict
could help here (From C11 (n1570) 6.7.3.1 “Formal definition of restrict
”, p4 [emph. mine]):
[In this case, B
is the inner block of foo_r
, P
is n_restr
, T
is const int
, and X
is the object denoted by *n
, I think.]
During each execution of
B
, letL
be any lvalue that has&L
based onP
. 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
shall not be const-qualified. […]
$ clang --version
Ubuntu clang version 3.5.0-4ubuntu2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Gcc version is 4.9.2, on an x86 32bit target.
doesnt_modify2
to cast away the constness and modify the object pointed to, as long as the object itself wasn't declaredconst
. – Hennahanerestrict
makes any difference here. – Ivon