c - 通过展开继承是否违反严格的别名规则?

标签 c inheritance struct strict-aliasing

我有一个继承自 struct Base 的 struct X。但是,在我当前的设置中,由于对齐,X 的大小为 24B:

typedef struct {
    double_t a;
    int8_t b;
} Base;

typedef struct {
    Base base;
    int8_t c;
} X;

为了节省内存,我想展开 Base 结构,所以我创建了结构 Y,它包含来自 Base 的字段(以相同的顺序,总是在结构的开头),所以结构是 16B:

typedef struct {
    double_t base_a;
    int8_t base_b;
    int8_t c;
} Y;

然后我将在需要指向 Base 结构的指针的方法中使用结构 Y 的实例:

void print_base(Base* b)
{
  printf("%f %d\n", b->a, b->b);
}
// ...
Y data;
print_base((Base*)&data);

上面的代码是否违反了严格的别名规则,并导致未定义的行为?

最佳答案

首先,BaseY 不是标准 6.2.7 定义的兼容类型,所有成员都必须匹配。

要通过 Base* 访问 Y 而不会造成严格的别名冲突,Y 需要是“聚合类型”(它is) 在其成员中包含一个 Base 类型。它没有。

所以这是一个严格的别名冲突,而且,由于 YBase 不兼容,它们可能有不同的内存布局。这就是重点,正是出于这个原因,您将它们设为不同的类型 :)

在这种情况下,您可以做的是对共享公共(public)初始序列 的结构成员使用 union ,这是一种允许的特殊情况。来自 C11 6.5.2.3 的有效代码示例:

union {
  struct {
    int alltypes;
  } n;
  struct {
    int type;
    int intnode;
  } ni;
  struct {
    int type;
    double doublenode;
  } nf;
} u;

u.nf.type = 1;
u.nf.doublenode = 3.14;
/* ... */
if (u.n.alltypes == 1)
  if (sin(u.nf.doublenode) == 0.0)

关于c - 通过展开继承是否违反严格的别名规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47710585/

相关文章:

c++ - 结构数组的动态分配

c++ - 如何计算作为输出打印的字符数?

c - 如何修复此表达式不可分配的错误?

我可以在不损失精度的情况下打印完全可表示的 float 吗?

Python 多继承,__init__

java - 将 Object 类作为 Java 类层次结构的根有什么好处?

objective-c - 在 block 内访问 C 数组(可变数组计数)Objective-C

c - 链接列表错误(语言: C)

python - 数据存储中的 GAE 继承

c - 访问结构中的字符指针字段