使用指针访问未对齐的结构体成员

6

我有以下结构体:

typedef struct __attribute__ ((__packed__))
{
    uint16_t a;
    uint32_t b;
} st_t;

-> "b" 成员未对齐。

当我执行以下操作时,gcc会发出警告:

st_t st;
uint32_t * b_p = &st.b;
*b_p = 0;

警告日志:

taking address of packed member of 'struct <anonymous>' may result in an unaligned pointer value

但是当我执行以下操作时,它没有引发任何警告:

st_t st;
st_t * st_p = &st;
st_p->b = 0;

我不理解为什么在第二种情况下没有引发警告,因为我仍在访问未对齐的成员。


2
请勿在提问中发布代码错误的图片,因为它们难以使用。请直接将文本作为问题的文字内容发布。 - MikeCAT
@MikeCAT 谢谢,我刚刚用文本替换了它。 - The_Average_Engineer
这里回答了一些关于编译器警告的原因。 - ryyker
难道不是在第一种情况下,您明确地指向了st.b的地址(由于打包可能会重新排列),而在第二种情况下,您告诉编译器“我要访问stb”,它会带您到那里(即让编译器“找出”如何做到这一点,因为它负责安排地址)? - Zakk
2个回答

5
无法提供标准报价,因此其他人肯定会写出更好的答案,但这里有一个简短的答案。
对于紧凑结构体,从“紧凑结构体”的定义来看,编译器必须为任何成员访问生成工作机器代码。未对齐的访问是已知的,并且将适当地处理 CPU。
然而,指向 int 的指针被认为指向有效的 int,这可能意味着它必须对齐(否则将出现“总线错误”或类似问题)。在那些关乎性能的 CPU 上,编译器为每个 int 指针解引用生成有效的未对齐访问机器代码相当低效,所以编译器基本上必须做出这种假设。
因此,如果编译器注意到指向未对齐地址的指针,则会发出警告,因为这是某些 CPU 上的非法操作,即使它是合法的,也可能比对齐访问慢。它不会为紧凑结构体发出警告,因为程序员通过使结构体紧凑来明确表示“这是未对齐的,请处理”。

2
C标准不认可“紧凑结构体”,因此C标准对其行为没有任何规定。 - Jonathan Leffler


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接