16

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

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

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

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

编辑:有趣的结果是,如果这实际上是一个别名违规,那么它似乎是一种在restrictC99 之前获得语义的 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 等作为不同的大小。

4

1 回答 1

6

您在这里不是通过不同类型的指针访问对象:您不是在操作 和 指向的数组对象,而是操作aandb指向的对象(*a)+5(*b)+0*((*a)+5)and *((*b)+0)。由于这些是指向同一类型的指针,因此它们很可能是同一对象的别名。

运算符的隐式赋值是对指向的对象++的有效赋值(*b)+0++x = x + 1x=

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

这里的类型完全一样,重叠是准确的。

于 2011-08-15T09:09:45.277 回答