单个成员结构的结构填充

ide*_*n42 4 c struct padding

我正在寻找一个任意大小的结构,在编译时已知。(用于宏)。

例如:

/* assume sizeof(SomeStruct) could be an odd number,
 * if it is using GCC's 'packed' attribute for eg */
struct {
    unsigned char data[sizeof(SomeStruct)];
} a, *tmp;

tmp = (void *)some_data
a = *tmp;
Run Code Online (Sandbox Code Playgroud)

然而,我担心struct填充可能会增加 的大小,struct因此它比成员更大,我确信单个成员的大小struct将始终是其成员的大小。

所以我的问题是:

我可以依赖单个成员结构始终与其成员大小相同吗?这是 C 规范的一部分吗?或者这就是大多数编译器的行为方式?

Leu*_*nko 6

C11 6.7.2.1 第 17 段:

结构或联合的末尾可能有未命名的填充。

对于只有一个成员的结构,没有列出特殊情况。这是实现定义的。

不过,编译器为何要在那里进行填充并不明显,因为成员的大小应该已经根据所有目的所需进行了填充,因为它有自己的完整类型。


不过,对于您的使用,您不需要依赖编译器的行为 - 您可以通过向您的宏添加静态断言来强制执行它sizeof *tmp == sizeof (SomeStruct)。如果您有最新的编译器并且您的宏允许声明语句,则只需使用_Static_assert; 您还可以使用一些与 C99 兼容的 hack,例如:

#define STATIC_EXPR_ASSERT(COND) (sizeof (char[(COND) ? 1 : -1]))
Run Code Online (Sandbox Code Playgroud)

...您可以将其用作逗号表达式的左侧。

您还应该注意,如果临时结构体由 char 数组组成,它可能没有足够的对齐来正确表示传入数据。从 C11 开始,您应该使用以下命令指定数组的对齐方式_Alignas

struct {
    _Alignas (max_align_t) unsigned char data[sizeof(SomeStruct)];
} a, *tmp;
Run Code Online (Sandbox Code Playgroud)

...这将确保它可以安全地存储任何类型的数据,无论对齐如何。在 C99 中,您没有任何方法显式请求最大对齐,但您可以通过使临时结构成为与其旁边的联合的成员来强制对齐与命名类型匹配(您可能会尝试并希望long double这是最对齐的类型)。

  • 假设 `struct{char foo;}Foo;`,那么 `sizeof(Foo)` 可以大于 `sizeof(char)`。因为编译器可以在任何边界自由设置 Foo 的对齐方式,但为了强制执行 sizeof(Foo[N])==N*sizeof(Foo) ,它必须在末尾进行填充。 (2认同)