对齐特定的pragma压缩结构成员的内存地址?

时间:2014-10-29 08:33:23

标签: c++ gcc

我有一个结构,其数据成员具有不同长度的类型(一些整数,一些单词,一些只是单个字节)。结构被打包(使用#pragma pack(1))。

我的问题是:是否有可能让结构的数据成员之一的内存地址在内存中对齐(例如,地址可以被16除掉)?

我知道可以使用属性对齐整个结构(或换句话说,它的第一个成员)。我想知道是否可以对齐特定成员而不仅仅是第一个成员。

基本上我需要打包结构(每个成员都遵循前一个没有填充的成员)并且我需要其中一个成员的地址而不是第一个成员的地址可以被16除掉。

2 个答案:

答案 0 :(得分:2)

似乎没有任何可能将结构与偏移对齐。您必须自己创建偏移量(填充)。

typedef struct __attribute__((packed)) special_align {
    char misc[3];
    int align_me;
};

typedef struct __attribute__((packed, aligned(16))) pad_container {
    char padding[13];   //16-3
    struct special_align data;
};

当然访问该结构将变得更加麻烦。 如果您不想手动计算所需的填充量,可以使用offsetof()宏。在示例中,offsetof(struct special_align,align_me)将返回3,即从对齐大小中减去。 (当然,如果偏移大于对齐,则必须使用相应的焊盘尺寸乘数。“

 pad_size = (sizeof(special_align) * align_size - offsetof(special_align,align_me)) % align_size;

答案 1 :(得分:0)

#pragma pack(1)是令人讨厌的 - 一旦为给定的结构设置它,它将适用于该结构的每个成员。 alignas__attribute__((packed, aligned(8)))std::aligned_storagestd::aligned_union#pragma pack()在该结构中构建的所有内容都不会影响对齐,原始包装将保留整个结构(中间#pragma pack()将适用于随后的任何内部结构,但外部结构将包装其原始包装。)

因此,唯一的解决方案是手动打包您的结构,方法是在必要时添加填充字节。

我正在使用这样的东西,它会触发编译器错误并显示(错误的)对齐方式:

template<int s> struct OffsetIs;

template<int N>
struct CheckAlignment {
  static constexpr size_t ok = sizeof(OffsetIs<N>);
};

template<>
struct CheckAlignment<0> {
  static constexpr bool ok = true;
};

#pragma pack(1)
struct MyStruct
{
  char a;
  //char pad[3]; // uncomment to make it compile
  long x;
};
#pragma pack()

static_assert(CheckAlignment<offsetof(MyStruct, x) % 4>::ok, "Alignment of x is wrong");