【问题标题】:Parameters declared restrict and compiler warnings声明的参数限制和编译器警告
【发布时间】:2015-08-19 19:04:34
【问题描述】:

gcc 5 和 clang 3.6 都不会在违反 restrict 限定符的约束时发出警告,即使使用 -Wall 调用也是如此。考虑以下代码片段:

extern void f(char *restrict p, char *restrict q);

void g(char *p)
{
    f(p, p);
}

天真地,我希望可以静态确定违规行为,并且我希望 -Wall 会发出警告。我是否错过了某处的标志,或者发出我没有看到的警告有什么问题?

【问题讨论】:

  • 原型中的顶级限定符没有意义(文档除外);函数体仍然可以实现为void f(char *p, char *q);。显然没有编译器会根据restrict 的存在来优化调用代码。 Related thread
  • 代替编译器开发人员实际发表评论 - 我的猜测只是没有人要求该功能和/或没有开发人员决定投入时间来实现它。

标签: c c99 c11 restrict restrict-qualifier


【解决方案1】:

从版本 8 开始,gcc 对上述代码给出了有用的警告:

a.c: In function ‘g’:
a.c:5:5: warning: passing argument 1 to restrict-qualified parameter aliases with argument 2 [-Wrestrict]
     f(p, p);
     ^

【讨论】:

    【解决方案2】:

    restrict 关键字是程序员明确保证所讨论的指针没有别名。本质上,它允许编译器省略对这些指针的别名分析,因为程序员已经提供了假定的答案。除了能够实现更好的优化之外,这还可以节省编译时间。在大型程序中,分析可能会非常昂贵,因此这本身就是一件大事。

    所以,我相信你的问题的答案是,“编译器没有在寻找,因为代码告诉他们不要打扰”

    【讨论】:

    • 这并不能真正回答我的问题。当编程错误很容易检测到时,我希望编译器会给我警告。
    【解决方案3】:

    给定代码:

    void test(int *restrict a, int *restrict b, int c)
    {
      a[0] += b[c];
    }
    

    restrict 限定符影响的唯一场景是a==b+c; 在这种情况下,a 中的指针将用于修改一个对象,该对象是 也可以通过b 中的无关指针访问。在所有其他情况下 将在没有restrict 的情况下定义,没有对象被访问 通过a 也可以通过b 访问,反之亦然。

    编译器可以看到传递的函数restrict- 限定的指针参数使用它们违反了相关的规则 因此可能有助于警告这种违规行为,但编译器不能 看到一个函数将无法知道哪些组合 参数将有效或无效。

    【讨论】:

    • union { struct { char d; int e; } f; int g } htest(&h.f.e, &h.g, 0) 是一个复杂的场景,可能会受到影响,即使测试参数 a==b+c 不正确。
    • @chux:N1570 标准草案的第 6.5p7 节禁止(恕我直言)授予 blanket 使用成员类型的任意左值访问聚合的权限,带或不带 @ 987654333@。如果通过从聚合派生的左值进行的访问有时被识别为(出于 6.5p7 的目的)是通过聚合类型而不是成员类型执行的,则这是有意义的。由于标准没有说明实现何时应该识别这种关联,这可能是一个实现质量问题。
    • @chux:在您描述的情况下,所编写的代码显然会调用 UB,因为对 a[0]b[c] 的操作仅在 b[c]a[0] 标识相同的完整时才会排序对象,而不是两个部分重叠的对象。如果将test 更改为int temp[b]c[; a[0]+=temp;,则可能会或可能不会定义此类代码,具体取决于使用从聚合派生的左值对堆存储的操作是否被视为纯粹基于派生类型或聚合设置有效类型类型。
    • 当前的做法似乎是,通过从聚合派生的左值对堆存储的操作至少有时被视为有效类型规则的目的,就好像它们是使用聚合类型执行的一样;鉴于缺乏通过成员类型左值访问聚合的全面许可,我认为标准不会对任何“重叠”场景中的代码行为提出任何要求。
    • restrict 的含义很难明确总结。感谢您的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 2019-10-18
    • 1970-01-01
    相关资源
    最近更新 更多