关于GCC / VS字节对齐

来源:互联网 发布:网络终结者p2p下载 编辑:程序博客网 时间:2024/06/04 04:36

    最近因为在写服务器程序,核心用户数据采用BLOB二进制保存到数据库中,其实就是将C/D++结构数据直接保存到数据库中。考虑到数据在Linux和Windows下都能用,就必须要考虑自己对齐的问题,否则GCC编译出来的程序(Linux下运行)生成的数据就不能在VS2012等Windows下编译出来程序使用。

   为了节省空间,采用4字节对齐方式,控制字节对齐的编译器选项网上有很多文章了,这里就不说了。VS下我对要控制字节对齐的结构都用如下语句定义:

#ifdef _WIN32
#pragma pack(push, 4)
#endif

struct User{

// ......

CMDSET *pSet;

//  ......

};


// other definition

// ......

#ifdef _WIN32
#pragma pack(pop)
#endif

GCC下则在每个结构加__attribute__((aligned(4))):

struct User{

//  ......

CMDSET *pSet;

//  ......

}__attribute__((aligned(4)));

合起来在一个文件中定义:

#ifdef _WIN32
#pragma pack(push, 4)
#endif


#ifdef _WIN32
#define ST_PACK_4
#else  
#define ST_PACK_4 __attribute__((aligned(4)))
#endif


struct User{

// ......

CMDSET *pSet;

//  ......

}ST_PACK_4;


// other definition

// ......

#ifdef _WIN32
#pragma pack(pop)
#endif

我编写的程序都是在64位环境下编译和运行,发现上面定义的User结构大小(sizeof(User)),VS下的比GCC少4字节,百思不得其解,最后通过取成员地址才发现两编译器对结构中指针成员的对齐处理方式有差异,GCC会将指针成员按8字节对齐方式放置,也就是说,

      GCC下结构的指针成员的地址是要被8整除的,即使你要求结构按4字节对齐也不影响这个规则

这就可能导致在结构的指针成员前面(编译器自动地)填充字节来保证适应上面的规则,也就导致了我发现的问题。


      当然解决这个问题可以使用多种方法:

1. 将结构中指针成员转成其他类型的成员,这会影响代码的实现

2. 调整结构中成员的顺序来保证指针成员地址刚好从8倍字节开始 (推荐这种方法)


附: 也许还应当考虑高低字节序的问题,但目前主要都是在IA(Intel Architecture)体系的机器下运行,基本都是LittleEndian的,所以就不考虑这问题会导致数据不可用啦。

0 0