c++ - 我必须关心 C++ 结构末尾的填充吗?我保证我不会在数组中使用它

标签 c++ g++ compiler-warnings clang++ memory-alignment

我有一个结构,不想隐式填充

#include <cstdint>
struct foo
{
  uint8_t a;
  uint32_t b;
};
static_assert(sizeof(foo) == 8, "");

我打开-Wpadded 警告。

> g++ test.cpp -c -Wpadded -std=c++14
test.cpp:5:12: warning: padding struct to align 'foo::b' [-Wpadded]
   uint32_t b;
            ^

> clang++ test.cpp -c -Wpadded -std=c++14
test.cpp:5:12: warning: padding struct 'foo' with 3 bytes to align 'b' [-Wpadded]
  uint32_t b;
           ^
1 warning generated.

太好了,这就是我想要的。

我现在要调换成员。我不关心最后的填充以使结构正确对齐。我宁愿将尺寸最小化。

#include <cstdint>
struct foo
{
  uint32_t b;
  uint8_t a;
};
static_assert(sizeof(foo) == 5, "");

> g++ test.cpp -c -Wpadded -std=c++14
test.cpp:2:8: warning: padding struct size to alignment boundary [-Wpadded]
 struct foo
        ^
test.cpp:7:1: error: static assertion failed:
 static_assert(sizeof(foo) == 5, "");
 ^

> clang++ test.cpp -c -Wpadded -std=c++14
test.cpp:2:8: warning: padding size of 'foo' with 3 bytes to alignment boundary [-Wpadded]
struct foo
       ^
test.cpp:7:1: error: static_assert failed ""
static_assert(sizeof(foo) == 5, "");
^             ~~~~~~~~~~~~~~~~
1 warning and 1 error generated.

这给了我一个我不想要的警告。

如果添加了隐式填充,但如果末尾缺少填充以对齐整个结构,我怎么会收到警告或编译时错误?我对使用它不感兴趣在一个数组中。或者这是一个冒险和粗心的事情允许吗?我确实需要正确对齐结构的实例。

是否有可以达到相同效果的属性或修饰符?

最佳答案

你可以这样做:

static_assert(offsetof(foo, b) == offsetof(foo, a) + sizeof(uint8_t), "");

当然,您需要在第一个成员之后为每个成员添加一个断言,或者更改上面的内容以包括所有字段,例如如果 c 是最后一个字段:

static_assert(offsetof(foo, c) == sizeof(uint8_t) + sizeof(uint32_t), "");

现在您可能想知道如何使它更加自动化。如果需要,您可以使用 Boost.Fusion...这是我按照这些思路提出并回答的问题:

Boost Fusion: validate adapted struct member ordering at compile time

您将使用相同的方法:将所有字段的大小加起来直到最后一个,并检查最后一个字段的偏移量是否相同。

关于c++ - 我必须关心 C++ 结构末尾的填充吗?我保证我不会在数组中使用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40078225/

相关文章:

C++ 自定义 vector 实现 - 指向不完整类型的指针的下标

c++ - 更好的编译器警告?

c - 禁用 -Wreturn 类型检查

c++ - isalpha 总是返回 0

c++ - 优化构造函数调用次数

c++ - C++ 中的非限定查找

c++ - 将 true/false 分配给 std::string:这是怎么回事?

c# - 获取错误 CS0031 : Constant value `65535' cannot be converted to a `short'

c++ - 我可以有一个带有可变对象的模板吗?

c++ - C++ 中的链接器正在接受具有相同参数和不同返回类型的函数,但我得到 SEGFAULT