我碰巧看了printf
(以及其他fprintf
类函数的原型) -
int printf(const char * restrict format, ...);
关键字restrict
如果我理解正确,如果其中一个标记为restrict
,则禁止通过两个指针访问同一个对象。
从C标准中引用相同内容的示例是here。
将格式标记为restrict
的一个好处我认为保存函数是因为格式字符串在执行期间可能被修改(比如因为%n
格式说明符)。
但这是否会产生更大的约束?这会使以下函数调用无效吗?
char format[] = "%s";
printf(format, format);
因为这里有明显的别名。为什么将restrict
关键字添加到format
的{{1}}参数?
答案 0 :(得分:6)
cppreference
在每次执行声明受限制指针
P
的块时(通常每次执行P
是函数参数的函数体),如果某个对象是可通过P
(直接或间接)进行修改,无论如何,,然后对该对象进行所有访问(包括读取和写入)< strong>在该块中必须通过P
(直接或间接)发生,否则行为未定义。
(强调我的)
这意味着:
char format[] = "%s";
printf(format, format);
定义明确,因为printf
不会尝试修改format
。
restrict
唯一未定义的是'在%…n
正在运行时使用printf
写入格式字符串'(例如char f[] = "%hhn"; printf(f, (signed char *)f);
)。
为什么将
restrict
关键字添加到printf
的格式参数?
restrict
本质上是编译器可能用来更好地优化代码的提示。
由于restrict
可能会或可能不会使代码运行得更快,但它永远不会让它变慢(假设编译器是理智的),它应该使用始终,除非:
答案 1 :(得分:1)
为什么printf中的格式标记为restrict?
int printf(const char * restrict format, ...);
restrict
中的some_type * restrict format
是&#34;合同&#34;在调用代码和函数printf()
之间。它允许printf()
假设format
指向的数据的唯一可能更改发生在函数直接执行的操作而不是其他指针的副作用。
这允许printf()
由与此类副作用不相关的更改格式字符串的代码组成。
由于format
指向const
数据,因此不允许printf()
更改数据。然而,这是restrict
功能的辅助功能。
考虑下面的病理代码。它违反了合同,printf()
肯定会改变*stdout
的状态,而状态又会改变.ubuf
。
strcpy(stdout->ubuf, "%s");
printf(stdout->ubuf, "Hello World!\n");
@HolyBlackCat有一个很好的"%n"
示例。
密钥:restrict
要求调用代码不作为format
传递,指向可能因printf()
操作而更改的字符串的任何指针。