数组指针别名 - 未定义的行为?
以下代码是否会调用未定义的行为(由于别名冲突或其他原因)?
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
语义的黑客但有效的方法。如:
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 等作为不同的大小。
Does the following code invoke undefined behavior (due to aliasing violation or otherwise)?
int foo(int (*a)[10], int (*b)[5])
{
(*a)[5]++;
return (*b)[0];
}
int x[10];
foo(&x, (int (*)[5])&x[5]);
Note that the corresponding code using plain int *
rather than pointer-to-array types would be perfectly legal, because a
and b
would be pointers to the same type and thus allowed to alias one another.
Edit: The interesting consequence, if this is in fact an aliasing violation, is that it seems to be a hackish but valid way to get restrict
semantics pre-C99. As in:
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 */
}
Presumably if you needed to access an actual array at each address, you could use SIZE_MAX-1 and SIZE_MAX-2 etc. as the differing sizes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您在这里不是通过不同类型的指针访问对象:您不是操作
a
和b
指向自身的数组对象,而是操作( 指向的对象*a)+5
和(*b)+0
,即*((*a)+5)
和*((*b )+0)
。由于这些是指向同一类型的指针,因此它们很可能是同一对象的别名。++
运算符的隐式赋值是对(*b)+0
指向的对象的有效赋值:++
等效到x = x + 1
(除了x
仅被评估一次)并且对于简单的赋值=
标准说这里的类型是完全一样的,并且重叠是准确的。
You are not accessing objects through pointers of different type here: you are not manipulating the array objects to which
a
andb
point themselves but the objects pointed to by(*a)+5
and(*b)+0
, namely*((*a)+5)
and*((*b)+0)
. Since these are pointers to the same type they may well alias to the same object.The implicit assignment by the
++
operator is a valid assignment to the object pointed to by(*b)+0
:++
is equivalent tox = x + 1
(besidesx
being evaluated only once) and for simple assignment=
the standard saysThe types here are exactly the same and the overlap is exact.