【问题标题】:Is restrict redundant for a const qualified pointer?对于 const 限定指针,restrict 是多余的吗?
【发布时间】:2016-10-06 21:50:13
【问题描述】:

如果我们将例如 f 和 g 定义为:

void f(const int *restrict a, const int *restrict b, int *c){ ... }
void g(const int *         a, const int *         b, int *c){ ... }
  1. 假设 f 和 g 具有等效的实体,从调用者的角度来看它们是否相同?
  2. 在被调用者中,我们可以对参数做同样的假设吗?
  3. 编译器有同样的优化机会吗?

如果restrict 是多余的,我希望所有三个答案都是肯定的。
否则,为什么不呢?

不要考虑不良的编程习惯,例如抛弃const 限定符。

【问题讨论】:

  • restrict 是一个难以理解的类型限定符,并且具有微妙的影响。建议避免快速选择答案。 (披露我确实在下面有一个答案),因为我非常有兴趣在这个有趣的帖子上看到其他人的答案。 (感谢新人提出的热门问题)
  • 确实,重复。如果该问题询问constint* const restrict a 中是否是多余的,这将是一个新的更好的问题

标签: c


【解决方案1】:

对于这种情况:

void f(const int *restrict a, const int *restrict b, int *c)

restrict 不是多余的。这意味着编译器可以假定ac 没有别名。例如,如果函数体是:

int d = *a;
*c = 5;
d = *a;

然后编译器可以删除第三行。


C11 6.7.3/7 涵盖了这一点:

此关联在下面的 6.7.3.1 中定义,要求所有访问 该对象直接或间接使用该特定指针的值。

也就是说,如果一个对象通过a访问,那么该对象是不允许通过bc访问的。

正式定义见C11 6.7.3.1/4(restrict的正式定义):

如果 L 用于访问它指定的对象 X 的值,并且 X 也被修改(以任何方式) ,则适用以下要求:T 不应是 const 限定的

这里Ta指向的声明类型,即const intL*aXac 指向的任何 int

【讨论】:

    【解决方案2】:

    不要考虑不良的编程习惯,例如抛弃 const 限定符。

    问题在于,即使在标准 C 中,指针上 const 的存在也不是绑定契约。这只是对程序员的建议,被调用者不会尝试修改指针。只要指针最初未被声明为 const 对象,代码实际上就可以修改指针(在转换之后)。

    因此,编译器不能安全地使用const:如果可能的话,他们仍然需要检查被调用者的内容以确保它没有说谎。

    【讨论】:

      【解决方案3】:

      编译器有同样的优化机会吗?

      如果我对the standard的理解正确,那么编译器对带有restrict限定指针的版本有更大的优化机会:

      在每次执行B [某个代码块] 期间,让L 成为基于P [restrict 限定指针] 具有&L 的任何左值。如果L 用于访问它指定的对象X 的值,并且X 也被修改(通过任何方式), 那么以下要求适用:T [P 指向的类型] 不应是 const 限定的。 [..]

      [N1570 §6.7.3.1/4,强调我的]

      从逻辑上讲,如果对象被修改,那么指向它的指针不应该是 const 限定的。因此,如果指针 是 const 限定的,则对象可能不会被修改(以任何方式)。

      Xmodified Tconst !Tconst Xmodified -> !Tconst
      true      true   false   false // oops, must disallow this case
      true      false  true    true
      false     true   false   true
      false     false  true    true
      

      因此,如果编译器看到T const * restrict,则可以确定该指针“后面”的对象在该指针的生命周期内不能被修改。这样……

      假设 f 和 g 具有等价的实体,从调用者的角度来看它们是否相同?

      ...这对调用者来说比只使用T const * 更有保障。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-20
        • 1970-01-01
        • 2012-02-17
        • 1970-01-01
        • 2016-10-02
        • 2014-12-08
        • 1970-01-01
        相关资源
        最近更新 更多