为什么printf中的格式标记为restrict?

时间:2018-06-13 16:15:26

标签: c printf restrict

我碰巧看了printf(以及其他fprintf类函数的原型) -

int printf(const char * restrict format, ...);

关键字restrict如果我理解正确,如果其中一个标记为restrict,则禁止通过两个指针访问同一个对象。

从C标准中引用相同内容的示例是here

将格式标记为restrict的一个好处我认为保存函数是因为格式字符串在执行期间可能被修改(比如因为%n格式说明符)。

但这是否会产生更大的约束?这会使以下函数调用无效吗?

char format[] = "%s";
printf(format, format);

因为这里有明显的别名。为什么将restrict关键字添加到format的{​​{1}}参数?

2 个答案:

答案 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可能会或可能不会使代码运行得更快,但它永远不会让它变慢(假设编译器是理智的),它应该使用始终,除非:

  • 使用它会导致UB
  • 在这种特定情况下没有显着的性能提升

答案 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()操作而更改的字符串的任何指针。