结构成员和指针对齐

时间:2015-02-09 20:30:12

标签: c pointers struct

指向结构的指针是否与指向第一个元素的指针对齐?

是指向结构的指针和指向其第一个成员类型(或反之亦然)的指针之间的转换吗?

(我希望他们是同一个问题......)

struct element
{
    tdefa x;
    tdefb y;
}; 

int foo(struct element* e);
int bar(tdefa* a);

~~~~~

tdefa i = 0;
foo((struct element*)&i);

struct element e;
bar((tdefa*)&e);

tdefatdefb可以定义为任何类型

背景:

我问了这个question 并且用户在其中一个答案的评论中提出了C11 6.3.2.3 p7,其中说明:

  

“指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   对于引用的类型对齐,行为未定义“

但是当我遇到问题时我遇到了麻烦,我的理解是填充将允许结构的所有成员正确对齐。我误解了吗?

以及如果:

struct element e;
tdefa* a = &e.x;

然后会工作:

tdefa* a = (tdefa*)&e;

也会。

2 个答案:

答案 0 :(得分:2)

从来没有任何初始填充;结构的第一个成员需要从与结构本身相同的地址开始。

您始终可以通过转换指向整个结构的指针来访问结构的第一个成员,作为指向第一个成员类型的指针。

您的foo示例可能遇到麻烦,因为foo期望其参数指向struct element,实际上它不会,并且可能存在对齐不匹配。< / p>

然而,bar示例和最后一个示例很好。

答案 1 :(得分:2)

指向结构的指针始终指向其初始成员。

这是直接来自C99 standard(6.7.2.1,第13段)的引文,强调我的:

  

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然。结构对象中可能有未命名的填充,但不是在其开头

至于您的foobar示例:

bar的调用没问题,因为bar需要tdefa,这正是它所获得的。

然而,对foo的调用存在问题。 foo需要完整struct element,但您只传递tdefa(而结构包含tdefa {{ 1}})。