C(++) 结构强制额外的填充
C(++) struct force extra padding
我已经看到了无数"我不喜欢填充如何关闭它"形式的问题,但还没有找到任何关于强制编译器提供额外填充的信息。
我的具体案例看起来像
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
};
其中vect2
是一个简单的struct {double x; double y;} vect2
. 为了使用 SSE2,我需要能够加载一对与 16 字节边界对齐的双精度。 这曾经有效,直到我添加了额外的int
,将我的结构大小从 48 字节推到 56 字节。 结果是段错误。
我可以使用某种编译器指令,要么说"填充此结构以使其成为 16 字节长的倍数",要么说"此结构的对齐方式为 16 字节"? 我知道我可以手动完成(例如,附加一个额外的字符[12]),但我真的宁愿告诉编译器(GCC,最好是 ICC 兼容),而不必手动执行此操作如果我将来更改结构。
在 gcc
中,你可以将任意类型和变量与 __attribute__((aligned(...)))
对齐。对于您的示例,这将是
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
} __attribute__((aligned (16)));
这会自动填充结构,以便其数组正确对齐。
您可以嵌套两个结构来自动填充它,而无需自己跟踪大小。
struct particle
{
// ...
};
{
particle p;
char padding[16-(sizeof(particle)%16)];
};
不幸的是,如果结构已经是 16 的倍数,则此版本会增加 16 个字节。这是不可避免的,因为标准不允许零长度的数组。
某些编译器确实允许零长度数组作为扩展,在这种情况下,您可以改为这样做:
struct particle_wrapper
{
particle p;
char padding[sizeof(particle)%16 ? 16-(sizeof(particle)%16) : 0];
};
如果结构已经是 16 的倍数,则此版本不会添加任何填充字节。
我正在为此添加自己的答案,以防有人来寻找解决方案。 Mark 的解决方案很简洁,满足了自动要求,但不是我最终选择的解决方案。 我想避免这种情况,这就是我问这个问题的原因,但有一个"微不足道"的解决方案:
struct particle{
vect2 s;
vect2 v;
int rX;
int rY;
double mass;
int boxNum;
char padding[12];
};
通过手动检查struct
的当前大小,您可以添加适当数量的字符(或其他任何内容,但char
允许您以字节为单位),以使其大小合适。 这显示了最佳性能和简单性,即使每次结构更改时都需要更新。 在这种情况下,这很好,尽管如果您有一个可以根据选项更改大小的结构,那将是有问题的。
请注意,我的struct
是 56 个字节,我添加了 12 个字节,使其成为 64 个字节。 该数学不起作用,因为尾随int
已经被填充了 4 个字节到 8 字节边界;struct
实际上只有 52 个字节。 仅添加 5 个 char
s 就可以工作,方法是将struct
长度设置为 57 字节,该长度将填充到 64,但这不是一个不错的解决方案,这就是为什么我使用 12 来使其完全工作。
未测试,但这可能有效:
#include <xmmintrin.h>
struct particle{
union {
vect2 s;
__m128 s_for_alignment;
};
union {
vect2 v;
__m128 v_for_alignment;
};
...
};
我知道 gcc 以前在正确对齐__m128
时遇到问题,但现在应该解决这些问题。
新的 C++11 规范也有一个新功能,尽管我不相信很多供应商已经实现了它们。
您可以尝试使用包编译指示,尽管规范不支持它。 不过,GCC和MS都支持它。
这会在 1 个字节边界上对齐结构,但您可以将数字更改为所需的任何数字。
#pragma pack(push,1)
// ...
#pragma pack(pop)
更新:
因此,显然上述内容将不起作用,因为它只会收缩填充,而不会扩展它。 遗憾的是,今天下午我没有测试环境。
也许使用匿名工会会起作用。 我知道它会扩展到最大的尺寸,尽管我不知道你是否能得到任何关于对齐的保证。
template<typename T, size_t padding_size>
struct padded_field {
union {
T value;
uint8_t padding[padding_size];
};
};
- 使用结构成员指针在C++中填充结构
- C++:使用缓冲区中的数据填充结构
- 用二进制文件填充结构
- 如何使用文件填充结构(下面附有的代码)?
- 使用 snprintf 填充结构
- 使用来自函数的指针填充结构数组
- 使用循环填充结构
- C 从文件中填充结构数组
- C 如何从UCHAR数组中填充结构的位字段
- 如何有效地用向量填充结构
- 避免在C 中填充结构
- 如何填充结构的向量
- C/C++ 从字符缓冲区读取以填充结构
- 从 std::vector<无符号字符中的数据填充结构>
- 从矢量中擦除元素,并向量填充结构
- 结构错误的构造函数(调用类的构造函数 denconstructor,用于填充结构)
- 有没有办法用较短的代码来填充结构
- 填充结构,同时查找min_element,C++
- 在函数中填充结构映射的最好方法是什么?
- 当编译器决定填充结构时