C99/C11限制类型限定符对没有定义的函数隐含任何含义吗? [英] Does C99/C11 restrict type qualifier imply anything for functions without definition?
问题描述
假设我们有一个无法访问其定义的函数声明:
Suppose we have a function declaration for which we do not have access to its definition:
void f(int * restrict p, int * restrict q, int * restrict r);
由于我们不知道如何访问指针,所以我们无法知道调用是否会触发未定义的行为,即使我们传递相同的指针(如6.7.3.1.10的示例所说明的那样):
Since we do not know how the pointers will be accessed, we cannot know if a call will trigger undefined behavior or not -- even if we are passing the same pointer, like the example at 6.7.3.1.10 explains:
函数参数声明:
The function parameter declarations:
void h(int n, int * restrict p, int * restrict q, int * restrict r)
{
int i;
for (i = 0; i < n; i++)
p[i] = q[i] + r[i];
}
说明如何通过两个受限制的指针为未修改的对象添加别名.尤其是,如果a
和b
是不相交的数组,则格式为h(100, a, b, b)
的调用具有已定义的行为,因为在功能h
中未修改数组b
.
illustrate how an unmodified object can be aliased through two restricted pointers. In particular, if a
and b
are disjoint arrays, a call of the form h(100, a, b, b)
has defined behavior, because array b
is not modified within function h
.
因此,除非作为调用者的提示/注释,否则restrict
在这些情况下是否多余,除非我们对该功能有更多了解?
Therefore, is restrict
superfluous in these cases, except as a hint/annotation for callers, unless we know something more about the function?
例如,让我们从标准库中获取sprintf
(7.21.6.6):
For instance, let's take sprintf
(7.21.6.6) from the standard library:
简介
#include <stdio.h>
int sprintf(char * restrict s,
const char * restrict format, ...);
说明
sprintf
函数与fprintf
等效,除了输出被写到数组(由参数s
指定)而不是流中. (...)
The sprintf
function is equivalent to fprintf
, except that the output is written into an array (specified by the argument s
) rather than to a stream. (...)
根据描述的摘要和第一句话,我们知道将写入s
,并且s
是受限制的指针.因此,我们是否可以假设(无需进一步阅读)像这样的调用:
From the synopsis and the first sentence of the description, we know that s
will be written to and that s
is a restricted pointer. Therefore, can we already assume (without reading further) that a call like:
char s[4];
sprintf(s, "%s", s);
会触发未定义的行为吗?
will trigger undefined behavior?
-
如果是,那么:
sprintf
描述的最后一句是否多余(即使已澄清)?
If yes, then: is the last sentence of
sprintf
's description superfluous (even if clarifying)?
如果在重叠的对象之间进行复制,则行为是不确定的.
If copying takes place between objects that overlap, the behavior is undefined.
否则,反过来:restrict
限定词是否多余,因为描述实际上是在让我们知道什么是未定义的行为?
If not, then, the other way around: is the restrict
qualifier superfluous since the description is the one that is actually letting us know what will be undefined behavior?
推荐答案
-
restrict
是在C99中引入的. -
Since we do not know how the pointers will be accessed, we cannot know if a call will trigger undefined behavior
是的.但这是信任的问题.函数声明是写函数定义的程序员与使用函数的程序员之间的契约.请记住,一旦使用C语言,我们只需要编写void f();
-这里的f是一个函数,它带有未指定数量的参数.如果您不相信编写该函数的程序员,那么没有人会也不会使用该函数.在C语言中,我们正在传递第一个数组元素的地址,因此,我看到这样声明的函数:我假设:编写该函数的程序员对如何使用这些指针或函数f使用它们作为指向单个元素的指针提供了一些说明,不是数组.
(在这种情况下,我喜欢在函数声明中使用C99 VLA来指定函数期望的数组长度:void f(int p[restrict 5], int q[restrict 10], int r[restrict 15]);
.此类函数声明与您的函数完全相同,但是您知道什么内存不能重叠.) -
char s[4]; sprintf(s, "%s", s);
会触发未定义的行为吗?
是的.在重叠且限制位置的对象之间进行复制,这是通过两个指针进行的. restrict
was introduced in C99.Since we do not know how the pointers will be accessed, we cannot know if a call will trigger undefined behavior
Yes. But this is a question of trust. A function declaration is a contract, between the programmer who wrote the function definition and programmer that uses the function. Remember, once in C we would just writevoid f();
- here f is a function that takes an unspecified number of parameters. If you don't trust that programmer who wrote that function, no one will and don't use that functions. In C we are passing address of the first array element, so seeing a function declared like this, I would assume: the programmer who wrote that function gives some description on how these pointers are used or function f uses them as pointers to single element, not as arrays.
( In times like this I like to use C99 VLAs in function declaration to specify how long arrays my function expects:void f(int p[restrict 5], int q[restrict 10], int r[restrict 15]);
. Such function declaration is exactly equal to yours, but you have some idea what memory can't overlap. )char s[4]; sprintf(s, "%s", s);
will trigger undefined behavior?
Yes. Copying takes place between objects that overlap and restrict location is accessed by two pointers.
这篇关于C99/C11限制类型限定符对没有定义的函数隐含任何含义吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!