10

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

我的具体情况看起来像

struct particle{
  vect2 s;
  vect2 v;
  int rX;
  int rY;
  double mass;
  int boxNum;
};

哪里vect2有简单的struct {double x; double y;} vect2。为了使用 SSE2,我需要能够加载一对双精度,对齐到 16 字节边界。这曾经有效,直到我添加了 extra int,将我的结构大小从 48 字节推到 56 字节。结果是段错误。

是否有某种编译器指令我可以使用,或者说“填充这个结构以使其长度为 16 字节的倍数”,或者“这个结构有 16 字节的对齐”?我知道我可以手动完成(例如添加一个额外的 char[12]),但我真的宁愿只告诉编译器(GCC,最好是 ICC 兼容),如果我更改了就不必手动完成未来的结构。

4

5 回答 5

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

于 2012-06-22T17:01:14.603 回答
6

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

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

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

于 2012-06-23T18:28:33.107 回答
3

我正在为此添加自己的答案,以防有人来寻找解决方案。马克的解决方案是一个简洁的解决方案,并且满足了自动要求,但它不是我最终选择的。我想避免这种情况,这就是我问这个问题的原因,但是有一个“微不足道”的解决方案:

struct particle{
  vect2 s;
  vect2 v;
  int rX;
  int rY;
  double mass;
  int boxNum;
  char padding[12];
};

通过手动检查 的当前大小struct,您可以添加适当数量的字符(或其他任何内容,但char允许您以字节为单位),以使其大小正确。这显示了最佳性能和简单性,即使每次结构更改时都需要更新。在这种情况下,这很好,尽管如果您有一个可以根据选项改变大小的结构,那将是有问题的。

请注意,mystruct是 56 字节,我添加了 12 使其成为 64。这个数学不起作用,因为尾随int已经被 4 字节填充到 8 字节边界;之前struct实际上只有 52 个字节。通过使 57 字节长,这将被填充到 64,只添加 5 chars 会起作用,struct但这不是一个很好的解决方案,这就是为什么我使用 12 来使其准确地工作。

于 2012-06-23T18:04:05.573 回答
1

新的 C++11 规范也为此提供了一个新功能,尽管我不相信很多供应商已经实现了它们。

您可以尝试 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];
    };
  };
于 2012-06-22T16:46:16.810 回答
1

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

#include <xmmintrin.h>

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

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

于 2012-06-22T16:52:32.680 回答