C 结构成员是否继承编译器属性?

Fre*_*rey 3 c gcc struct memory-alignment

对于大多数 C 编译器,可以在结构上指定编译器属性,该属性定义该结构的成员在内存中的对齐方式。前任:

typedef struct{
    char a;
    char b;
} __attribute__((aligned(2))) TwoChars;

Run Code Online (Sandbox Code Playgroud)

如果char a以地址 0xA 结束(为简单起见),则char b不会在地址 0xB 处,而是在 0xC 处,因为它与 2 个字节对齐。

我的问题是:这个属性是由结构成员继承的吗?前任:

typedef struct{
    char a;
    char b;
} TwoChars;

typedef struct {
    TwoChars tc;
    char c;
} __attribute__((aligned(1))) ThreeChars;
Run Code Online (Sandbox Code Playgroud)

这在内存中最终会是什么样子?怎么样} __attribute__((aligned(2))) TwoChars

Mar*_*lli 5

注意:这是一个非标准的编译器特定扩展。我在回答中提到的内容可能适用于 GCC 和 Clang,我认为这就是“大多数 C 编译器”的意思。


可以在结构上指定编译器属性,该属性定义该结构的成员在内存中的对齐方式

不,这不是__attribute__((aligned(...)))工作方式。该aligned属性仅适用于结构本身,而不适用于其字段。请参阅相关文档页面

如果要控制结构字段的对齐方式,则必须对它们使用该属性。

这个:

struct {
    char a;
    char b;
} __attribute__((aligned(8))) foo = { 1, 2 };
Run Code Online (Sandbox Code Playgroud)

将编译为类似:

foo:
    .byte   1
    .byte   2
    .zero   6
Run Code Online (Sandbox Code Playgroud)

虽然这个:

foo:
    .byte   1
    .byte   2
    .zero   6
Run Code Online (Sandbox Code Playgroud)

会做你想做的:

bar:
    .byte   1
    .zero   1
    .byte   2
    .zero   1
Run Code Online (Sandbox Code Playgroud)

所以:

这个属性是由结构成员继承的吗?

不。对齐不是结构成员继承的东西。


一个有趣的事情是,如果该packed属性被应用它的结构内的嵌套结构的成员继承,因为packed它专门由结构成员继承。文档没有明确说明是否是这种情况,但我们可以很容易地检查这一点。

以下代码:

struct {
    char a __attribute__((aligned(2)));
    char b __attribute__((aligned(2)));
} bar = { 1, 2 };
Run Code Online (Sandbox Code Playgroud)

编译为:

x:
    .byte   101
    .zero   3
    .long   102
    .byte   103
    .zero   3
    .byte   104
    .long   105        
Run Code Online (Sandbox Code Playgroud)

从上面我们可以看出,packed仅适用于 的成员,bar并且不会被 的成员继承foo,而添加__attribute__((packed))foo会产生以下结果:

x:
    .byte   101
    .long   102
    .byte   103
    .byte   104
    .long   105
Run Code Online (Sandbox Code Playgroud)

如果您想知道,这也适用于在其他结构中定义的结构:

struct bar {
    struct {
        char a;
        int b;
        char c;
    } d;
    char e;
    int c;
} __attribute__((packed));

struct bar x = {{101, 102, 103}, 104, 105};
Run Code Online (Sandbox Code Playgroud)

产生:

x:
    .byte   101
    .zero   3
    .long   102
    .byte   103
    .zero   3
    .byte   104
    .long   105        
Run Code Online (Sandbox Code Playgroud)

而添加__attribute__((packed))d产生:

x:
    .byte   101
    .long   102
    .byte   103
    .byte   104
    .long   105
Run Code Online (Sandbox Code Playgroud)