我有一个问题,即在编译时应检查结构 - 如果它已经很好地对齐或者它是否包含间隙。 检查可以在其他测试代码中完成,但我不希望在实际实现代码中使用“打包”数据。
这是一个带有典型包含警卫的示例头文件(MyData.h):
http.ErrUseLastResponse
我找到了一种可能的解决方案 - 见下文。
问题:
在编译时,是否有一种优雅的方法来检查struct #ifndef MYDATA_H_
#define MYDATA_H_
struct uneven
{
int bla_u32;
short bla_u16;
char bla_u8;
/* <-- this gap will be filled in the unpacked version */
};
#endif // MYDATA_H
是否包含与其解包对应字节不同的字节数?
是否有可能在C中使用的解决方案(不使用命名空间)?
答案 0 :(得分:5)
适用于C和C ++的特定于编译器的解决方案:GCC有一个警告选项-Wpadded
,它会为每个因对齐而改变大小的定义生成警告。
答案 1 :(得分:3)
您可以使用函数而不是命名空间(on ideone):
此解决方案也适用于C
标题文件:
typedef struct
{
int bla_u32;
short bla_u16;
char bla_u8;
/* <-- this gap will be filled in the unpacked version */
} uneven;
源文件:
#include "MyData.h"
#define StaticAssert(cond, msg) switch(0){case 0:case cond:;}
void checkSizes()
{
uneven unpacked_uneven;
#pragma pack(push, 1)
#undef MYDATA_H_ // force re-including "MyData.h"
#include "MyData.h"
#pragma pack(pop)
uneven packed_uneven;
StaticAssert(sizeof(unpacked_uneven) == sizeof(packed_uneven), "uneven contains gaps");
}
您可以将StaticAssert
放入函数中以进行编译时错误。
答案 2 :(得分:2)
我找到了一个(某种程度上令人讨厌且非常棘手)解决方案,解决了只适用于C ++而不是C的问题。
uneven
对于给定的不均匀结构数据,此#define StaticAssert(cond, msg) switch(0){case 0:case cond:;}
#pragma pack(push, 1)
namespace packed
{
#include "MyData.h"
}
#pragma pack(pop)
#undef MYDATA_H_ // force re-including "MyData.h"
#include "MyData.h"
void checkSizes()
{
StaticAssert(sizeof(packed::uneven) == sizeof(uneven), "uneven contains gaps");
}
宏失败 - 因为打包版本的大小为7个字节,而解压缩(正常)版本为8个字节。如果在结构的末尾添加了额外的StaticAssert
,则测试成功 - 两个版本都有8个字节。