数组指针别名 - 未定义的行为?

时间:2011-08-15 04:39:27

标签: c undefined-behavior aliasing

以下代码是否会调用未定义的行为(由于别名违规或其他原因)?

int foo(int (*a)[10], int (*b)[5])
{
    (*a)[5]++;
    return (*b)[0];
}

int x[10];
foo(&x, (int (*)[5])&x[5]);

请注意,使用普通int *而不是指针到数组类型的相应代码是完全合法的,因为ab将是指向同一类型的指针,因此允许彼此别名。

编辑:有趣的结果,如果这实际上是一个别名违规,那么它似乎是一种在C99之前获得restrict语义的一种hackish但有效的方法。如:

void some_func(int *aa, int *bb)
{
    int (*a)[1] = (void *)aa;
    int (*b)[2] = (void *)bb;
    /* Now **a and **b can be assumed by the compiler not to alias */
}

假设您需要访问每个地址的实际数组,您可以使用SIZE_MAX-1和SIZE_MAX-2等作为不同的大小。

1 个答案:

答案 0 :(得分:5)

您不是通过不同类型的指针访问对象:您不是在操纵ab指向自己的数组对象,而是(*a)+5指向的对象和{ {1}},即(*b)+0*((*a)+5)。由于它们是指向相同类型的指针,因此它们可能是同一对象的别名。

*((*b)+0)运算符的隐式赋值是对++指向的对象的有效赋值:(*b)+0等同于++x = x + 1除外仅评估一次)和简单分配x标准说

  

如果从另一个对象读取存储在对象中的值   以任何方式重叠第一个对象的存储,然后是   重叠应准确,两个对象应具有合格或   兼容类型的不合格版本;否则,行为是       未定义。

这里的类型完全相同,重叠是精确的。