如何使C++结构体大小为成员大小的倍数并保持聚合特性
问题描述
现有如下结构体:
struct employee { std::string name; short salary; std::size_t age; };
以Linux amd64平台为例,该结构体大小为48字节,而std::string的大小为32字节,二者并非倍数关系。
需求是跨平台(如同时支持Linux amd64和Apple ARM)让employee的大小为其第一个成员std::string大小的倍数,即满足sizeof(employee) % sizeof(std::string) == 0,同时要保持结构体的聚合类特性。
已尝试的方案及问题
方案1:使用alignas
尝试用alignas控制整个类或成员的填充,但alignas要求对齐值必须是2的幂次,限制过于严格,无法满足“大小为第一个成员大小的倍数”的需求。
方案2:添加末尾填充数组
尝试在结构体末尾添加char数组作为填充,但遇到两个核心问题:
- 编译期填充大小计算不优雅:
最初尝试用dummy类计算填充大小,写法冗余且逻辑正确性存疑:struct employee_dummy { std::string name; short salary; std::size_t age; }; struct employee { std::string name; short salary; std::size_t age; char padding[(sizeof(employee_dummy)/sizeof(std::string)+1)*sizeof(std::string) - sizeof(employee_dummy)]; }; - 破坏聚合初始化特性:
若将填充成员设为私有,虽然能隐藏实现,但必须添加构造函数,导致结构体不再是聚合类:struct employee { std::string name; short salary; std::size_t age; private: char padding[(sizeof(employee_dummy)/sizeof(std::string)+1)*sizeof(std::string) - sizeof(employee_dummy)]; };
核心疑问
如何通过标准或非标准机制控制结构体大小为其第一个成员大小的倍数,同时保持其聚合类特性?
补充说明
后续意识到填充大小的计算需要考虑结构体原有填充(即最后一个成员的偏移量),公式会更复杂。例如希望data的大小为第一个成员std::complex<double>大小的倍数时:
struct dummy { std::complex<double> a; double b; std::int64_t b2; int c; }; struct data { std::complex<double> a; double b; std::int64_t b2; int c; char padding[ ((offsetof(dummy, c) + sizeof(c)) / sizeof(std::complex<double>) + 1)* sizeof(std::complex<double>) - (offsetof(dummy, c) + sizeof(c)) ]; };
内容的提问来源于stack exchange,提问作者alfC
相关产品推荐
相关产品推荐

