通过展开继承是否违反了严格的别名规则? [英] Does inheritance via unwinding violate strict aliasing rule?

查看:164
本文介绍了通过展开继承是否违反了严格的别名规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a struct X which inherits from struct Base. However, in my current setup, due to alignment, size of X is 24B:

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

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

为了保存内存,我想解开Base结构,所以我创建了struct Y包含Base中的字段(以相同的顺序,始终在struct的开头),因此struct的大小为16B:

In order to save the memory, I'd like to unwind the Base struct, so I created struct Y which contains fields from Base (in the same order, always at the beginning of the struct), so the size of the struct is 16B:

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

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

Then I'm going to use instance of struct Y in a method which expects a pointer to Base struct:

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

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

Does the code above violates the strict aliasing rule, and causes undefined behavior?

推荐答案

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

First, Base and Y are not compatible types as defined by the standard 6.2.7, all members must match.

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

To access an Y through a Base* without creating a strict aliasing violation, Y needs to be "an aggregate type" (it is) that contains a Base type among its members. It does not.

所以这是一个严格的别名违规,而且,因为 Y Base 不兼容,它们可能有不同的内存布局。这就是重点,因为这个原因你把它们变成了不同的类型:)

So it is a strict aliasing violation and furthermore, since Y and Base are not compatible, they may have different memory layouts. Which is kind of the whole point, you made them different types for that very reason :)

在这样的情况下你可以做的是使用带有struct成员的联合共享公共初始序列,这是一个特殊的允许案例。来自C11 6.5.2.3的有效代码示例:

What you can do in situations like this, is to use unions with struct members that share a common initial sequence, which is a special allowed case. Example of valid code from 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)

这篇关于通过展开继承是否违反了严格的别名规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆