zeb*_*h49 9 c c++ gcc struct memory-alignment
我已经看到了无数问题的形式"我不喜欢填充如何关闭它",但还没有找到任何关于强制编译器提供额外填充的内容.
我的具体情况看起来像
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
};
Run Code Online (Sandbox Code Playgroud)
哪里vect2
很简单struct {double x; double y;} vect2
.为了使用SSE2,我需要能够加载一对双精度数,对齐到16字节边界.这曾经工作,直到我添加额外的int
,将我的结构大小从48字节推到56字节.结果是段错误.
是否有某种编译器指令我可以使用"填充此结构使其成为16字节长的倍数",或"此结构具有16字节的对齐"?我知道我可以手动完成(例如,添加一个额外的字符[12]),但我真的只是告诉编译器(GCC,最好是ICC兼容),如果我改变它,就不必手动完成结构在未来.
您可以嵌套两个结构来自动填充它,而无需自己跟踪大小.
struct particle
{
// ...
};
{
particle p;
char padding[16-(sizeof(particle)%16)];
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果结构已经是16的倍数,那么这个版本增加了16个字节.这是不可避免的,因为标准不允许零长度的数组.
有些编译器允许零长度数组作为扩展,在这种情况下,您可以这样做:
struct particle_wrapper
{
particle p;
char padding[sizeof(particle)%16 ? 16-(sizeof(particle)%16) : 0];
};
Run Code Online (Sandbox Code Playgroud)
如果结构已经是16的倍数,则此版本不会添加任何填充字节.
在gcc
,您可以使用对齐任意类型和变量__attribute__((aligned(...)))
.对于你的例子,这将是
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
} __attribute__((aligned (16)));
Run Code Online (Sandbox Code Playgroud)
这会自动填充结构,以便正确对齐其数组.
我正在添加我自己的答案,以防有人来寻找解决方案。马克的解决方案是一个简洁的解决方案,并且满足自动要求,但它不是我最终采用的。我想避免这种情况,这就是我问这个问题的原因,但有一个“微不足道”的解决方案:
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
char padding[12];
};
Run Code Online (Sandbox Code Playgroud)
通过手动检查 的当前大小struct
,您可以添加适当数量的字符(或其他任何内容,但char
可以让您以字节为单位执行此操作),以使其大小正确。这显示了最佳性能以及简单性,尽管它确实需要在每次结构更改时进行更新。在这种情况下,这很好,但如果您有一个可以根据选项更改大小的结构,那就会出现问题。
请注意,我的struct
大小是 56 个字节,我添加了 12 个字节使其成为 64 个字节。这个数学运算不起作用,因为尾部int
已经被填充了 4 个字节到 8 字节边界;struct
之前实际上只有 52 字节。只添加 5char
秒就可以了,通过使struct
57 个字节长,这将被填充到 64,但这不是一个很好的解决方案,这就是为什么我使用 12 来使它准确地工作。