【问题标题】:passing argument 1 of 'func' discards 'restrict' qualifier from pointer target type传递“func”的参数 1 从指针目标类型中丢弃“restrict”限定符
【发布时间】:2018-02-22 11:33:40
【问题描述】:

为什么在这种情况下不允许丢弃restrict限定符?

void func(double * const *q) {
    q[0][0] = 10.0;
}

int main(void) {
    double a = 5.0;
    double * restrict p = &a;
    double * restrict const *q = &p;

    // GCC: warning: passing argument 1 of 'func' discards 'restrict' qualifier
    // from pointer target type [-Werror=discarded-qualifiers]
    func(q);

    return 0;
}

这个错误看起来很不直观,因为一个限制指针可以转换为一个非限制指针,这里用const 确保func 不能用非限制指针替换p

【问题讨论】:

  • 警告说func允许修改参数。它可能不会现在这样做并不会改变它可以这样做的事实。
  • restrict 限定符指示编译器您将仅使用此指针来访问指向的内存,但无法检查您是否真的这样做(在主代码或函数中)。在函数方面,您声明了一个 const 指针,该指针可以复制到函数内部的不同指针中,允许非限制访问,在这种情况下,编译器在编译函数时无法生成警告。然后在没有显式强制转换的情况下传递指针,这可能是函数内部问题的可能来源,最终不是自愿的..
  • 在将double * restrict 发送到仅采用double * 的某个函数时,不能使用关于制作副本的相同参数吗?然后再次复制指针并获得非限制访问。

标签: c restrict


【解决方案1】:

所有类型限定符的一般规则是,您可以安全隐式地将指针类型转换为限定指针类型。这由 6.3.2.3 以及简单赋值规则 6.5.16.1(在参数传递期间适用)保证。这同样适用于所有限定符:constvolatilerestrict_Atomic

这并不意味着你可以反过来。您永远不能隐式删除限定符,您必须使用显式强制转换。当你这样做时,你调用了实现定义的行为。

在这种情况下,演员表是完全安全的:func((double*const *)q);

值得注意的是,restrict 在用于函数参数并且您从另一个翻译单元调用这些函数时最有意义。在本地范围内使用restrict 可能意义不大,因为编译器可以轻松推断出表达式中涉及的变量是指向不同地址还是相同地址。

总的来说,它是程序员和编译器之间的“契约”,程序员承诺不会通过任何其他变量访问指向的数据。然而,程序员可以通过丢弃restrict 轻松打破这个契约,然后任何事情都可能发生。

【讨论】:

    猜你喜欢
    • 2013-03-02
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    相关资源
    最近更新 更多