指向结构的指针是否与指向第一个元素的指针对齐?
或
是指向结构的指针和指向其第一个成员类型(或反之亦然)的指针之间的转换吗?
(我希望他们是同一个问题......)
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);
tdefa
和tdefb
可以定义为任何类型
背景:
我问了这个question 并且用户在其中一个答案的评论中提出了C11 6.3.2.3 p7,其中说明:
“指向对象类型的指针可以转换为指向a的指针 不同的对象类型。如果结果指针不正确 对于引用的类型对齐,行为未定义“
但是当我遇到问题时我遇到了麻烦,我的理解是填充将允许结构的所有成员正确对齐。我误解了吗?
以及如果:
struct element e;
tdefa* a = &e.x;
然后会工作:
tdefa* a = (tdefa*)&e;
也会。
答案 0 :(得分:2)
从来没有任何初始填充;结构的第一个成员需要从与结构本身相同的地址开始。
您始终可以通过转换指向整个结构的指针来访问结构的第一个成员,作为指向第一个成员类型的指针。
您的foo
示例可能遇到麻烦,因为foo
期望其参数指向struct element
,实际上它不会,并且可能存在对齐不匹配。< / p>
然而,bar
示例和最后一个示例很好。
答案 1 :(得分:2)
指向结构的指针始终指向其初始成员。
这是直接来自C99 standard(6.7.2.1,第13段)的引文,强调我的:
在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然。结构对象中可能有未命名的填充,但不是在其开头
foo
和bar
示例:对bar
的调用没问题,因为bar
需要tdefa
,这正是它所获得的。
然而,对foo
的调用存在问题。 foo
需要完整struct element
,但您只传递tdefa
(而结构包含tdefa
和 {{ 1}})。