结构成员和指针对齐
structure members and pointer alignment
指向结构的指针是否对齐,就好像它是指向第一个元素的指针一样?
或
指向结构的指针和指向其第一个成员类型(反之亦然)的指针之间的转换曾经是 UB 吗?
(我希望他们是同一个问题...)
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
可以定义为任何类型
背景:
我问这个
一位用户在对其中一个答案的评论中提出了 C11 6.3.2.3 p7,其中指出:
"A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined"
但是我无法确定这何时会成为问题,我的理解是填充将允许结构的所有成员正确对齐。我是不是误会了?
如果:
struct element e;
tdefa* a = &e.x;
然后会起作用:
tdefa* a = (tdefa*)&e;
也会。
从来没有任何初始填充;结构的第一个成员必须从与结构本身相同的地址开始。
您始终可以通过将指针转换为整个结构来访问结构的第一个成员,使其成为指向第一个成员类型的指针。
您的 foo
示例可能 运行 会遇到麻烦,因为 foo
期望它的参数指向一个 struct element
而实际上它并没有,而且可能是对齐不匹配。
但是 bar
示例和最后一个示例很好。
指向结构的指针始终指向其初始成员。
这是直接来自 C99 standard 的引文(6.7.2.1,第 13 段),强调我的:
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning
至于你的 foo
和 bar
例子:
对 bar
的调用会很好,因为 bar
期望 tdefa
,这正是它得到的结果。
但是,对 foo
的调用是有问题的。 foo
期望完整的 struct element
,但您只传递了 tdefa
(而该结构由 tdefa
和 tdefb
).
指向结构的指针是否对齐,就好像它是指向第一个元素的指针一样?
或
指向结构的指针和指向其第一个成员类型(反之亦然)的指针之间的转换曾经是 UB 吗?
(我希望他们是同一个问题...)
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
可以定义为任何类型
背景:
我问这个
"A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined"
但是我无法确定这何时会成为问题,我的理解是填充将允许结构的所有成员正确对齐。我是不是误会了?
如果:
struct element e;
tdefa* a = &e.x;
然后会起作用:
tdefa* a = (tdefa*)&e;
也会。
从来没有任何初始填充;结构的第一个成员必须从与结构本身相同的地址开始。
您始终可以通过将指针转换为整个结构来访问结构的第一个成员,使其成为指向第一个成员类型的指针。
您的 foo
示例可能 运行 会遇到麻烦,因为 foo
期望它的参数指向一个 struct element
而实际上它并没有,而且可能是对齐不匹配。
但是 bar
示例和最后一个示例很好。
指向结构的指针始终指向其初始成员。
这是直接来自 C99 standard 的引文(6.7.2.1,第 13 段),强调我的:
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning
至于你的 foo
和 bar
例子:
对 bar
的调用会很好,因为 bar
期望 tdefa
,这正是它得到的结果。
但是,对 foo
的调用是有问题的。 foo
期望完整的 struct element
,但您只传递了 tdefa
(而该结构由 tdefa
和 tdefb
).