我有一个结构,其数据成员具有不同长度的类型(一些整数,一些单词,一些只是单个字节)。结构被打包(使用#pragma pack(1))。
我的问题是:是否有可能让结构的数据成员之一的内存地址在内存中对齐(例如,地址可以被16除掉)?
我知道可以使用属性对齐整个结构(或换句话说,它的第一个成员)。我想知道是否可以对齐特定成员而不仅仅是第一个成员。
基本上我需要打包结构(每个成员都遵循前一个没有填充的成员)并且我需要其中一个成员的地址而不是第一个成员的地址可以被16除掉。
答案 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_storage
,std::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");