C99/C11限制类型限定符对没有定义的函数隐含任何含义吗? [英] Does C99/C11 restrict type qualifier imply anything for functions without definition?

查看:124
本文介绍了C99/C11限制类型限定符对没有定义的函数隐含任何含义吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个无法访问其定义的函数声明:

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];
}

说明如何通过两个受限制的指针为未修改的对象添加别名.尤其是,如果ab是不相交的数组,则格式为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 write void 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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆