gpt4 book ai didi

c - 严格的别名和覆盖继承

转载 作者:太空狗 更新时间:2023-10-29 16:53:40 25 4
gpt4 key购买 nike

考虑这个代码示例:

#include <stdio.h>

typedef struct A A;

struct A {
int x;
int y;
};

typedef struct B B;

struct B {
int x;
int y;
int z;
};

int main()
{
B b = {1,2,3};
A *ap = (A*)&b;

*ap = (A){100,200}; //a clear http://port70.net/~nsz/c/c11/n1570.html#6.5p7 violation

ap->x = 10; ap->y = 20; //lvalues of types int and int at the right addrresses, ergo correct ?

printf("%d %d %d\n", b.x, b.y, b.z);
}

我曾经认为将 B* 转换为 A* 并使用 A* 操纵 B* 对象是严格的别名违规行为。但后来我意识到标准实际上只需要:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 1) a type compatible with the effective type of the object, (...)

和诸如 ap->x 之类的表达式确实具有正确的类型和地址,并且 ap 的类型在那里应该无关紧要(或者是吗?) .在我看来,这意味着只要子结构不作为一个整体进行操作,这种类型的覆盖继承就是正确的。

这种解释是否有缺陷或表面上与标准作者的意图不一致?

最佳答案

带有 *ap = 的行是一个严格的别名违规:B 类型的对象是使用 A 类型的左值表达式编写的.

假设那条线不存在,我们移动到 ap->x = 10; ap->y = 20;。在这种情况下,int 类型的左值用于写入 int 类型的对象。

关于这是否是严格的别名违规存在分歧。我认为标准的字母说明它不是,但其他人(包括 gcc 和 clang 开发人员)认为 ap->x 暗示 *ap 被访问。大多数人同意该标准对严格别名的定义过于模糊,需要改进。

使用您的结构定义的示例代码:

void f(A* ap, B* bp)
{
ap->x = 213;
++bp->x;
ap->x = 213;
++bp->x;
}

int main()
{
B b = { 0 };
f( (A *)&b, &b );
printf("%d\n", b.x);
}

对我来说,这在 -O2 处输出 214,在 -O3 处输出 2,使用 gcc。在 godbolt 上为 gcc 6.3 生成的程序集是:

f:
movl (%rsi), %eax
movl $213, (%rdi)
addl $2, %eax
movl %eax, (%rsi)
ret

这表明编译器已将函数重新安排为:

int temp = bp->x + 2;
ap->x = 213;
bp->x = temp;

因此编译器必须考虑到 ap->x 可能不会为 bp->x 设置别名。

关于c - 严格的别名和覆盖继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42352681/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com