I just happened to look at the prototype of the printf
(and other fprintf
class of functions) -
int printf(const char * restrict format, ...);
The keyword restrict
if I understand correctly disallows access to the same object through two pointers if one of them is marked restrict
.
An example that cites the same from the C standard is here.
One benefit of marking the format as restrict
I think is saving the function from the chance that the format string might get modified during the execution (say because of the %n
format specifier).
But does this impose a bigger constraint? Does this make the following function call invalid?
char format[] = "%s";
printf(format, format);
Because there is clearly an aliasing here. Why was the restrict
keyword added to the format
argument of printf
?
The
restrict
insome_type * restrict format
is a "contract" between the calling code and the functionprintf()
. It allows theprintf()
to assume the only possible changes to the data pointed to byformat
occur to what the function does directly and not a side effect of other pointers.This allows
printf()
to consist of code that does not concern itself with a changing format string by such side effects.Since
format
points toconst
data,printf()
is not also allowed to change the data. Yet this is ancillary to therestrict
feature.Consider pathological code below. It violates the contract as
printf()
may certainly alter the state of*stdout
, which in turn can alter.ubuf
.@HolyBlackCat has a good
"%n"
example.Key:
restrict
requires the calling code to not pass asformat
, any pointer to a string that may change due toprintf()
operation.(emphasis mine)
It means that:
Is well-defined because
printf
won't attempt to modifyformat
.The only thing that
restrict
makes undefined is 'writing to the format string using%…n
whileprintf
is running' (e.g.char f[] = "%hhn"; printf(f, (signed char *)f);
).restrict
is essentially a hint the compiler might use to optimize your code better.Since
restrict
may or may not make code run faster, but it can never make it slower (assuming the compiler is sane), it should be used always, unless: