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
?
cppreference
During each execution of a block in which a restricted pointer
P
is declared (typically each execution of a function body in whichP
is a function parameter), if some object that is accessible throughP
(directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur throughP
(directly or indirectly), otherwise the behavior is undefined.
(emphasis mine)
It means that:
char format[] = "%s";
printf(format, format);
Is well-defined because printf
won't attempt to modify format
.
The only thing that restrict
makes undefined is 'writing to the format string using %…n
while printf
is running' (e.g. char f[] = "%hhn"; printf(f, (signed char *)f);
).
Why was the
restrict
keyword added to the format argument ofprintf
?
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:
Why is the format in printf marked as restrict?
int printf(const char * restrict format, ...);
The restrict
in some_type * restrict format
is a "contract" between the calling code and the function printf()
. It allows the printf()
to assume the only possible changes to the data pointed to by format
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 to const
data, printf()
is not also allowed to change the data. Yet this is ancillary to the restrict
feature.
Consider pathological code below. It violates the contract as printf()
may certainly alter the state of *stdout
, which in turn can alter .ubuf
.
strcpy(stdout->ubuf, "%s");
printf(stdout->ubuf, "Hello World!\n");
@HolyBlackCat has a good "%n"
example.
Key: restrict
requires the calling code to not pass as format
, any pointer to a string that may change due to printf()
operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With