打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
结构对齐
写8位机没有这个问题,但是写ARM,则会遇到内存对齐的问题,比如这么一个结构体:struct cmdHead
{
 u8 cValid;   //命令头
 u16 nAddress;  //地址 -- 预留
 u8 cCmdMajor;  //主命令
 u8 cCmdMinor;  //次命令
 u16 nPacketCur;  //当前包号
 u16 nPacketAll;  //总包数
 u16 nDataSize;  //数据长度
 u8 cCrc;   //校验
 u8 *pData;   //数据
}; 
当将一个u8的buf强制转换成该结构体时,就会发现,第一个成员u8 cValid会占用2个字节,这个是32位机的内存强制对齐的规则造成的,为了能正确使用这个结构体,可以在声明时加个关键字:
typedef __packed struct

__packed struct
 cmdHead

也可以

#pragma pack(push,1)

typedef  struct 
{
}
cmdHead;

#pragma pack(pop)

 
不过要注意的是,强制单字节对齐后,会降低ARM的效率,所以慎用,最好的解决方法还是在定义结构体的时候就注意一下内存对齐的规则 


========================================================
http://blog.csdn.net/yesongldz/article/details/6077653

1 ANSI C规定


      ANSI C规定一种结构类型的大小是它所有字段的大小以及字段之间或字段尾部的填充区大小之和。

      填充区就是为了使结构体字段满足内存对齐要求而额外分配给结构体的空间。

 

      那么结构体本身有对齐要求,ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松,可以更严格。

 

2  WIN32和Linux平台下的对齐基本规则

 

      许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k
(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。


    Win32平台下的微软C编译器(cl.exe for 80x86)在默认情况下采用如下的对齐规则:


    任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,

而char类型数据(1字节)则可以从任何一个地址开始。


    Linux下的GCC奉行的是另外一套规则(在资料中查得,并未验证,如错误请指正):
    任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)

都以4为对齐模数。

 

3 vc6中对齐处理


    vc6中的编译选项有 /Zp[1|2|4|8|16] ,/Zp1表示以1字节边界对齐,相应的,/Zpn表示以n字节边界对齐。
n字节边界对齐的意思是说,一个成员的地址必须安排在成员的尺寸的整数倍地址上或者是n的整数倍地址上,取它们中的最小值。
也就是:
    min ( sizeof ( member ),  n)
    
实际上,1字节边界对齐也就表示了结构成员之间没有空洞。 
    
    要使用这个选项,可以在vc6中打开工程属性页,c/c++页,选择Code Generation分类,在Struct member alignment可以选择。

 

    /Zpn选项是应用于整个工程的,影响所有的参与编译的结构。该缺省/Zp 紧凑值为/Zp8,也就是说,缺省是8字节对齐。

    要专门针对某些结构定义使用对齐选项,可以使用#pragma pack编译指令。

 

#pragma pack(push) //保存对齐状态
#pragma pack(1)   // 1 bytes对齐

typedef struct 
{
    double dValue1;
    char   u8Value2;
    int    u32Value3;
} ASampleStructor;

#pragma pack(pop)//恢复对齐状态

 

    上例中,size值为13,说明1字节对齐后,该结构总长为13字节。去掉对齐后,为16字节。


4 ARM平台中的对齐

 

    在ARM平台的编译器中,没有提供象“#pragma pack”这么丰富的带参数对齐指令,只有一个关键字“__packed”。

__packed 限定符将所有有效类型的对齐边界设置为 1,如果一个结构没有这个限定符,默认向表数能力最强的那个数据类型对齐。

 

typedef __packed struct 
{
    double dValue1;
    char   u8Value2;
    int    u32Value3;
} ASampleStructor;

 

上例中,size值为13,说明1字节对齐后,该结构总长为13字节。去掉__packed对齐后,为16字节。

 

5 一种与对齐相关的可随时运行在VC环境或ARM(Keil)环境下的定义

 

       我们时常会把嵌入式平台上的代码拿到PC环境中去测试,这时环境的差异将使代码移植变得困难。

下面这种结构,将会使移植变得非常轻松。

 

#ifdef WIN32

#define __packed  //在VC环境下,将此关键字定义为空

 

#pragma pack(push) //保存对齐状态
#pragma pack(1)   // 1 bytes对齐

#endif

 

typedef __packed struct 
{
    double dValue1;
    char   u8Value2;
    int    u32Value3;
} ASampleStructor;

 

#ifdef WIN32

#pragma pack(pop)//恢复对齐状态

#endif

 

     这样,无论是ARM还是VC,都可以编译,代码的同步将非常简单。

 

     不过呢,还有一种方法更为简单,可以使代码运行在ARM(Keil)或VC环境下。

#pragma pack(push,1)

typedef  struct 
{
    double dValue1;
    char   u8Value2;
    int    u32Value3;
} ASampleStructor;

#pragma pack(pop)


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C/C++中的对齐
ARM的字对齐问题总结
内存对齐与ANSI C中struct内存布局
C语言结构体及其内存布局
C语言
实例讲解C语言编程中的结构体对齐
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服