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

发布于 2024-11-29 17:12:42 字数 663 浏览 1 评论 0原文

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

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语义的黑客但有效的方法。如:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愁以何悠 2024-12-06 17:12:42

您在这里不是通过不同类型的指针访问对象:您不是操作 ab 指向自身的数组对象,而是操作 ( 指向的对象*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 and b 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 to x = x + 1 (besides x being evaluated only once) and for simple assignment = the standard says

If the value being stored in an object is read from another object
that overlaps in any way the storage of the first object, then the
overlap shall be exact and the two objects shall have qualified or
unqualified versions of a compatible type; otherwise, the behavior is
undefined.

The types here are exactly the same and the overlap is exact.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文