通过展开继承是否违反了严格的别名规则? [英] Does inheritance via unwinding violate strict aliasing rule?
问题描述
我有一个继承自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屋!