我有一个从struct base继承的struct x。但是,在我当前的设置中,由于对齐,x的大小为24b:

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

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

为了节省内存,我想展开基结构,所以我创建了包含基字段的结构y(顺序相同,总是在结构的开头),因此结构的大小是16b:
typedef struct {
    double_t base_a;
    int8_t base_b;
    int8_t c;
} Y;

然后我将在一个方法中使用struct y的实例,该方法需要指向基结构的指针:
void print_base(Base* b)
{
  printf("%f %d\n", b->a, b->b);
}
// ...
Y data;
print_base((Base*)&data);

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

最佳答案

首先,BaseY不是标准6.2.7定义的兼容类型,所有成员必须匹配。
若要通过Y访问Base*,而不创建严格的别名冲突,Y需要是“聚合类型”(它是),在其成员中包含Base类型。不是的。
因此,这是一种严格的别名冲突,而且,由于YBase不兼容,它们可能具有不同的内存布局。这就是全部的观点,你们让它们有不同的类型是因为这个原因:)
在这种情况下,您可以做的是与共享公共初始序列的结构成员一起使用联合,这是一种特殊的允许情况。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/

10-11 18:07