Chinaunix首页 | 论坛 | 博客
  • 博客访问: 441105
  • 博文数量: 126
  • 博客积分: 35
  • 博客等级: 民兵
  • 技术积分: 1262
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 16:39
文章分类

全部博文(126)

文章存档

2017年(2)

2016年(20)

2015年(64)

2014年(24)

2013年(16)

我的朋友

分类: C/C++

2013-10-30 16:10:41

以下测试代码里,结构体A2的对齐方式,gcc 3.4.6和4.1.2是不一样
  1. #include <stdio.h>

  2. #pragma pack(push)
  3. #pragma pack(1)
  4. struct a1
  5. {
  6.     short a;
  7.     int b;
  8.     char c;
  9. }A1;
  10. #pragma pack(pop)

  11. struct a2
  12. {
  13.     short a;
  14.     int b;
  15.     char c;
  16. }A2;

  17. int main()
  18. {
  19.     printf("sizeof(A1):%d\n",sizeof(A1));
  20.     printf("sizeof(A2):%d\n",sizeof(A2));
  21. }
gcc 3.4.6编译时,会有警告:
  1. pack.cpp:3: warning: malformed '#pragma pack(push[, id], <n>)' - ignored
  2. pack.cpp:11: warning: #pragma pack (pop) encountered without matching #pragma pack (push, <n>)
运行结果是:
  1. sizeof(A1):7
    sizeof(A2):7
gcc 4.1.2编译时没有警告,运行结果是:
  1. sizeof(A1):7
  2. sizeof(A2):12
由此可见,#pragma pack(push)gcc 3.4.6认为malformed,被忽略了,而#pragma pack (pop)而则没有与之相匹配的push,#pragma pack(1)一直生效着,结构体A2就不幸中枪了。

各家编译器对与pack的解释不一样,微软官网,Visual Studio 2013 VS支持 
#pragma pack(show),gcc不支持。对于pop,VS、gcc的不同版本貌似有不一样的理解。
微软的解释里写着
#pragma pack(pop, identifiern) is undefined.
但是在The following sample shows how to use the pushpop, and show syntax.里又给了一个
例子:
#pragma pack(pop, r1, 2) // n = 2 , stack popped

最稳妥的办法,就是#pragma pack(n)#pragma pack()配合使用,是什么就是什么,压栈、出栈比较复杂。
或者用下面这种格式,对每个要按字节对齐的结构体单独说明:
  1. #ifndef PACK
  2. #define PACK __attribute__ ((packed))
  3. #endif

  4. typedef struct a
  5. {
  6.      char a;
  7.      int b;
  8. }PACK A;

2014.03.31
补记:分X汇X服务器在某服务器上出现了使用#pragma pack(n)#pragma pack()出错,而使用#pragma pack(push,n)#pragma pack(pop)则(表现得)没有错误的现象。怀疑是其程序其他地方有bug,待验证。
其程序原来把几个头文件也放到了按字节对齐的代码块里,运行很久竟然没有发现,无论是否运行正常,这种写法是极其错误的,更正后仍存在上述问题,待解。


阅读(5576) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~