【问题标题】:Can the `restrict` keyword be used in the function definition only?`restrict` 关键字只能在函数定义中使用吗?
【发布时间】:2021-03-01 20:55:35
【问题描述】:

我想知道是否可以将 restrict 关键字仅包含在函数定义中,而不是像这样的函数声明中:

void foo(char *bar);

void foo(char * restrict bar)
{
    // do something
}

由于foo 只接受一个参数,任何指针别名都必须在foo 内进行。调用函数的人不需要知道restrict 修饰符。像const一样,只在函数声明中省略关键字可以吗?

【问题讨论】:

  • 注意:这些声明不是针对个人的,而是针对编译器的。
  • "调用函数的人不需要知道限制修饰符" --> 不是这样。考虑int fred[42]; foo(fred)foo() 与全局fred[] 混淆。该调用违反了restrict
  • @chux-ReinstateMonica 为什么会这样?我认为只要函数内部没有像 char *p = bar 这样的事情发生就可以了。
  • @tadman: 函数定义中的restrict 用于编译器,但声明中的参数restrict 用于程序员,编译器会忽略它。

标签: c keyword


【解决方案1】:

您可以在函数声明中的参数上使用restrict,无论它们是否是定义,因为它是C 语法允许的,并且没有禁止它的规则。但是,它们在非定义的声明中对编译器没有影响。这是因为 6.5.2.2 7 说在将参数传递给带有原型的函数时,限定符被删除:

...参数被隐式转换为相应参数的类型,就像通过赋值一样,将每个参数的类型作为其声明类型的非限定版本。

因此,如果函数声明具有int * restrict a 类型的参数,则您传递的任何参数都将转换为非限定类型int *

此外,即使更改了参数上的限定符,两个其他方面相同的函数声明也是兼容的,因为 C 2018 6.7.6.3 15 说:

…(在确定类型兼容性和复合类型时,…用限定类型声明的每个参数都被视为具有其声明类型的非限定版本。)

但是,这仅适用于参数本身。该参数不受限定它的restrict 影响。但它可以指向一个限制限定的指针。比如void foo(void * restrict *a);void foo(void **a);声明了不同的函数类型。

虽然声明中参数的限定符对编译器没有影响,但它们可以向人类发出信号,表明参数应该符合限制。在函数定义中,参数是限制限定的,任何调用函数的人都应该尊重这一点。

【讨论】:

  • 我想在声明中包含它也可以帮助编译器提供更好的警告或优化。
  • "6.5.2.2 7 says qualifiers are removed" 重要的是要注意这是传递类型本身使用的限定符,而不是指向类型的限定符。 “好像通过赋值”部分意味着我们不能将 const int* 传递给期望 int* 的函数,但我们可以传递 int* const,因为这就是赋值规则的表述方式。
  • 最后,从标准到引用的相关部分是关于左值转换的规则 6.3.2.1/2 "...将没有数组类型的左值转换为存储在中的值指定对象(不再是左值);这称为左值转换。如果左值具有限定类型,则该值具有左值类型的非限定版本;"
  • @Lundin:答案确实说明限定符已从参数类型中删除,并且确实指出指向的指针可以是限制限定的。
  • @Lundin: 6.3.2.1 2 无关紧要,因为参数类型由 6.5.2.2 7 规定。无论 6.3.2.1 2 在左值转换期间是否删除限定符,参数都会转换为参数根据 6.5.2.2 7 的类型,表示它们被转换为非限定类型。相反,如果 6.5.2.2 7 说它们被转换为带有它们的限定符的参数类型,那么无论左值转换做了什么,它们都会被它们的限定符转换为它们的参数类型。 6.3.2.1 2 对此没有影响。
猜你喜欢
  • 1970-01-01
  • 2017-09-15
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 2022-07-21
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多