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

R..*_*R.. 14 c undefined-behavior pointer-aliasing

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

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

int x[10];
foo(&x, (int (*)[5])&x[5]);
Run Code Online (Sandbox Code Playgroud)

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

编辑:有趣的结果,如果这实际上是一个别名违规,是它似乎是一个hackish但有效的方式来获得restrictC99之前的语义.如:

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 */
}
Run Code Online (Sandbox Code Playgroud)

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

Jen*_*edt 5

你是不是通过不同类型这里指针访问对象:你是不是操纵数组对象到ab指向自己,但对象指向(*a)+5(*b)+0,即*((*a)+5)*((*b)+0).由于它们是指向相同类型的指针,因此它们可能是同一对象的别名.

++运算符的隐式赋值是对指向的对象的有效赋值(*b)+0:++相当于x = x + 1(除了x仅被评估一次)并且对于简单赋值=,标准说

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

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