代码之家  ›  专栏  ›  技术社区  ›  arsenm

这是限制指针的无效使用吗?

  •  6
  • arsenm  · 技术社区  · 15 年前

    void foo(float* array, float c, unsigned int n)
    {
        for (unsigned int i = 0; i < n; ++i)
            array[i] *= c;
    }
    
    void bar(float* restrict array, float* restrict array2, unsigned int m, unsigned int n)
    {
        for (unsigned int i = 0; i < m; ++i)
            foo(&array[i * n], array2[i], n);
    }
    

    这是否违反了将部分数组的地址传递给foo()的bar()中restrict的规则,即使您从未在bar()中真正使用数组的一部分的别名?

    2 回复  |  直到 13 年前
        1
  •  9
  •   Gilles 'SO- stop being evil'    15 年前

    N1256 ,即C99+技术勘误表(TC3)。)

    形式化定义 restrict 见§6.7.3.1。我引用下面最重要的一条。 P -类型的限定指针 T 谁的范围是块 B . 指针表达式 E 据说是 基于 指向。

    ,让 L 任何左值 &L 用于访问对象的值 X 它指定的,和 同时(通过任何方式)进行修改,则适用以下要求:

    • 用于访问 地址也应基于
    • 每次修改 也应考虑修改 ,就本款而言。
    • 基于另一个受限指针对象的 P2 ,与块关联 B2 ,则 地下二层 应在合同执行前开始 B类 ,或执行

    如果不满足这些要求,则行为是未定义的。


    让我们看看规则对访问 bar array 在里面 foo . 我们从 数组 酒吧 . 为了清楚起见,我将alpha转换

    void foo(float* b, float c, unsigned int n) { /*modify b[i]*/ }
    

    指向的存储 数组 也可以通过 b . 第二点没关系 &array[i*n] 相当于 array+(i*n)

    b类 他是合格的 ,那么我们就得用 b类 , , 数组 , 地下二层 酒吧 . 自 B类 嵌套在 (函数的行为就像这里内联的一样,见§6.7.3.1.11),满足第一个条件。第三个要点也有一个实例(访问 b[i] 在里面 )这不是问题。

    然而 b类 不合格。根据§6.3.2.3.2,对于任何限定符 -类型的限定版本;存储在原始指针和转换指针中的值应相等。因此,从 数组+(i*n) 定义良好并且具有明显的含义,因此定义了程序的行为。此外,由于 不是 -合格,不需要遵守任何线性条件。例如,以下 酒吧

    void qux(float *v, float *w) {
        v[0] += w[0];
    }
    void foo(float* b, float c, unsigned int n)
    {
        qux(b,b);
    }
    

    补充 :要解决在bar()中将部分数组的地址传递给foo()的特定问题,这不是问题: 限制 应用于指针,而不是数组,您可以对其执行算术运算(要点2)。

        2
  •  -2
  •   Spudd86    15 年前

    不,restrict意味着数组不能别名任何东西,所以您可以在不违反规则的情况下将内容传递给bar

    推荐文章