C(++)struct强制额外填充

时间:2012-06-22 16:41:47

标签: c++ c gcc struct memory-alignment

我已经看过无数的问题形式“我不喜欢填充如何将其关闭”,但还没有找到任何关于强制编译器提供额外填充的内容。

我看起来像

的具体情况
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兼容),如果我改变它,就不必手动完成未来的结构。

5 个答案:

答案 0 :(得分:8)

您可以嵌套两个结构来自动填充它,而无需自己跟踪大小。

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的倍数,则此版本不会添加任何填充字节。

答案 1 :(得分:5)

gcc中,您可以将任意类型和变量与__attribute__((aligned(...)))对齐。对于您的示例,这将是

struct particle{
  vect2 s;
  vect2 v;
  int rX;
  int rY;
  double mass;
  int boxNum;
} __attribute__((aligned (16)));

这会自动填充结构体,以使其数组正确对齐。

答案 2 :(得分:3)

我正在为此添加自己的答案,以防有人来寻找解决方案。马克的解决方案是一个很好的解决方案,并满足自动要求,但它不是我最终的时候。我想避免这种情况,这就是为什么我问这个问题,但是有一个“微不足道”的解决方案:

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来让它完全解决。

答案 3 :(得分:1)

新的C ++ 11规范也有new feature,但我不相信很多供应商已经实现了它们。

您可以尝试使用pack pragma,但规范不支持。 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];
    };
  };

答案 4 :(得分:1)

未经测试,但这可能有效:

#include <xmmintrin.h>

struct particle{
  union {
    vect2 s;
    __m128 s_for_alignment;
  };
  union {
    vect2 v;
    __m128 v_for_alignment;
  };
  ...
};

我知道gcc之前有正确对齐__m128的问题,但现在应该修复这些问题。