为什么 printf 中的格式标记为 restrict?
Why is the format in printf marked as restrict?
我只是碰巧看了 printf
的原型(以及其他 fprintf
class 函数)-
int printf(const char * restrict format, ...);
如果我理解正确,关键字 restrict
不允许通过两个指针访问同一对象,如果其中一个指针被标记为 restrict
。
引用 C 标准的相同示例是 here。
我认为将格式标记为 restrict
的一个好处是可以避免函数在执行期间可能会修改格式字符串(比如由于 %n
格式说明符)。
但这是否施加了更大的限制?这是否会使以下函数调用无效?
char format[] = "%s";
printf(format, format);
因为这里明显是走样了。为什么要将 restrict
关键字添加到 printf
的 format
参数中?
cppreference
During each execution of a block in which a restricted pointer P
is declared (typically each execution of a function body in which P
is a function parameter), if some object that is accessible through P
(directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P
(directly or indirectly), otherwise the behavior is undefined.
(强调我的)
意思是:
char format[] = "%s";
printf(format, format);
定义明确,因为 printf
不会尝试修改 format
。
restrict
唯一未定义的是 'writing to the format string using %…n
while printf
is running'(例如 char f[] = "%hhn"; printf(f, (signed char *)f);
)。
Why was the restrict
keyword added to the format argument of printf
?
restrict
本质上是编译器可能用来更好地优化代码的提示。
由于 restrict
可能会或可能不会使代码 运行 更快,但它永远不会使其变慢(假设编译器是正常的),因此应该 始终,除非:
- 使用它会导致 UB
- 在这种特定情况下,它没有显着提高性能
Why is the format in printf marked as restrict?
int printf(const char * restrict format, ...);
some_type * restrict format
中的restrict
是调用代码和函数printf()
之间的"contract"。它允许 printf()
假定对 format
指向的数据的唯一可能更改发生在函数直接执行的操作上,而不是其他指针的副作用。
这允许 printf()
包含不关心由此类副作用引起的格式字符串更改的代码。
由于format
指向const
数据,所以printf()
也不允许更改数据。然而,这是 restrict
功能的附属功能。
考虑下面的病态代码。它违反了合同,因为 printf()
肯定会改变 *stdout
的状态,而 *stdout
又会改变 .ubuf
.
strcpy(stdout->ubuf, "%s");
printf(stdout->ubuf, "Hello World!\n");
有一个很好的例子 "%n"
。
关键:restrict
要求调用代码不作为 format
传递,任何指向可能因 printf()
操作而改变的字符串的指针。
我只是碰巧看了 printf
的原型(以及其他 fprintf
class 函数)-
int printf(const char * restrict format, ...);
如果我理解正确,关键字 restrict
不允许通过两个指针访问同一对象,如果其中一个指针被标记为 restrict
。
引用 C 标准的相同示例是 here。
我认为将格式标记为 restrict
的一个好处是可以避免函数在执行期间可能会修改格式字符串(比如由于 %n
格式说明符)。
但这是否施加了更大的限制?这是否会使以下函数调用无效?
char format[] = "%s";
printf(format, format);
因为这里明显是走样了。为什么要将 restrict
关键字添加到 printf
的 format
参数中?
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.
(强调我的)
意思是:
char format[] = "%s";
printf(format, format);
定义明确,因为 printf
不会尝试修改 format
。
restrict
唯一未定义的是 'writing to the format string using %…n
while printf
is running'(例如 char f[] = "%hhn"; printf(f, (signed char *)f);
)。
Why was the
restrict
keyword added to the format argument ofprintf
?
restrict
本质上是编译器可能用来更好地优化代码的提示。
由于 restrict
可能会或可能不会使代码 运行 更快,但它永远不会使其变慢(假设编译器是正常的),因此应该 始终,除非:
- 使用它会导致 UB
- 在这种特定情况下,它没有显着提高性能
Why is the format in printf marked as restrict?
int printf(const char * restrict format, ...);
some_type * restrict format
中的restrict
是调用代码和函数printf()
之间的"contract"。它允许 printf()
假定对 format
指向的数据的唯一可能更改发生在函数直接执行的操作上,而不是其他指针的副作用。
这允许 printf()
包含不关心由此类副作用引起的格式字符串更改的代码。
由于format
指向const
数据,所以printf()
也不允许更改数据。然而,这是 restrict
功能的附属功能。
考虑下面的病态代码。它违反了合同,因为 printf()
肯定会改变 *stdout
的状态,而 *stdout
又会改变 .ubuf
.
strcpy(stdout->ubuf, "%s");
printf(stdout->ubuf, "Hello World!\n");
"%n"
。
关键:restrict
要求调用代码不作为 format
传递,任何指向可能因 printf()
操作而改变的字符串的指针。