单个成员结构的结构填充

时间:2015-03-22 15:05:31

标签: 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;

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

所以我的问题是:

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

1 个答案:

答案 0 :(得分:4)

C11 6.7.2.1第17段:

  

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

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

为什么编译器 将填充放在那里并不明显,因为成员的大小应该已经为所有目的所需的填充,因为它具有完整的类型它自己的。


但是,对于您的使用,您不需要依赖编译器的行为 - 您可以通过向宏sizeof *tmp == sizeof (SomeStruct)添加静态断言来自行实施。如果你有一个最新的编译器,你的宏允许声明语句,只需使用_Static_assert;您还可以使用几种与C99兼容的黑客,例如:

#define STATIC_EXPR_ASSERT(COND) (sizeof (char[(COND) ? 1 : -1]))

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

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

指定数组的对齐方式
struct {
    _Alignas (max_align_t) unsigned char data[sizeof(SomeStruct)];
} a, *tmp;

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