以下代码是否会调用未定义的行为(由于别名违规或其他原因)?
int foo(int (*a)[10], int (*b)[5])
{
(*a)[5]++;
return (*b)[0];
}
int x[10];
foo(&x, (int (*)[5])&x[5]);
请注意,使用普通int *
而不是指针到数组类型的相应代码是完全合法的,因为a
和b
将是指向同一类型的指针,因此允许彼此别名。
编辑:有趣的结果,如果这实际上是一个别名违规,那么它似乎是一种在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等作为不同的大小。
答案 0 :(得分:5)
您不是通过不同类型的指针访问对象:您不是在操纵a
和b
指向自己的数组对象,而是(*a)+5
指向的对象和{ {1}},即(*b)+0
和*((*a)+5)
。由于它们是指向相同类型的指针,因此它们可能是同一对象的别名。
*((*b)+0)
运算符的隐式赋值是对++
指向的对象的有效赋值:(*b)+0
等同于++
(x = x + 1
除外仅评估一次)和简单分配x
标准说
如果从另一个对象读取存储在对象中的值 以任何方式重叠第一个对象的存储,然后是 重叠应准确,两个对象应具有合格或 兼容类型的不合格版本;否则,行为是 未定义。
这里的类型完全相同,重叠是精确的。