linux c/c++常用关键字pragma pack和attribute_packed总结

(一)pragma pack使用说明
用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题,有时候为了内存对齐需要补齐空字节。通常写程序的时候,不需要考虑对齐问题。编译器会替我们选择适合目标平台的对齐策略。当然,我们也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法。
语法:#pragma pack( [show] | [push | pop] [, identifier], n )
#pragma pack() 能够取消自定义的对齐方式,恢复默认对齐。
作用:指定结构,联合和类的包对齐方式(pack alignment)
例子如下:
(说明,64位GCC,默认8字节对齐)

//这个就规定了4字节对齐
#pragma   pack(4) 
struct C {
    double d;
    char b;
    int a;
};
//默认8字节对齐
#pragma pack() 
struct B {
    double d;//8
    char b;//1(8)
    int a; //4
};
C:8+4+4=16
B:8+8=16 

#pragma pack(push)
#pragma pack(4)
struct ......
#pragma pack(pop)

//
总结:
(1)这样在push和pop之间的结构体就可以按照pack指定的字节(这里是4字节对齐方式),而pop之后的结构体按照#pragma pack(push) 前对齐方式。
(2)#pragma pack() 取消自定义对齐方式,恢复默认方式,而push之后pop是回到push指令之前的对齐方式。
(3)#pragma pack(push):英文单词push是“压入”的意思。编译器编译到此处时将保存对齐状态(保存的是 push指令之前的对齐状态)。
#pragma pack(pop):英文单词pop是”弹出“的意思。编译器编译到此处时将恢复push指令前保存的对齐状态(请在使用该预处理命令之前使用#pragma pack(push))。
push和pop是一对应该同时出现的名词,只有pop没有push不起作用,只有push没有pop可以保持之前对齐状态(但是这样就没有使用push的必要了)

(二)_attribute_详解

  1. ***attribute ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐***,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的。例如:

在Turbo C下:struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;(紧凑模式)

在GCC下:struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;(非紧凑模式)

在GCC下:struct my{ char ch; int a;}attrubte ((packed)) sizeof(int)=4;sizeof(my)=5

  1. attribute__关键字主要是用来在函数或数据声明中设置其属性。给函数赋给属性的主要目的在于让编译器进行优化。函数声明中的__attribute((noreturn)),就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码。

GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:

attribute ((attribute-list))

其位置约束:放于声明的尾部“;”之前。

函数属性(Function Attribute):函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用 –Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

packed属性:使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。

如果你看过GPSR协议在TinyOS中的实现,你一定会注意到下面的语句:

typedef struct {
    double x;
    double y;
} __attribute__((packed)) position_t;

GNU C的一大特色(却不被初学者所知)就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
__attribute__语法格式为:
attribute ((attribute-list))

其位置约束为:放于声明的尾部“;”之前。

packed是类型属性(Type Attribute)的一个参数,使用packed可以减小对象占用的空间。需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也是无济于事的。

使用该属性对struct或者union类型进行定义,设定其类型的每一个变量的内存约束。当用在enum类型定义时,暗示了应该使用最小完整的类型(it indicates that the smallest integral type should be used)。

下面的例子中,my-packed-struct类型的变量数组中的值会紧凑在一起,但内部的成员变量s不会被“pack”,如果希望内部的成员变量也被packed的话,my-unpacked-struct也需要使用packed进行相应的约束。

struct my_unpacked_struct
{
     char c;
     int i;
};
         
struct my_packed_struct
{
     char c;
     int i;
     struct my_unpacked_struct s;
}__attribute__ ((__packed__));

总结:结构体后面加上__attribute__ ((packed))即是不用字节对齐。

在每个系统上看下这个结构体的长度吧。
内存对齐,往往是由编译器来做的,如果你使用的是gcc,可以在定义变量时,添加__attribute__,来决定是否使用内存对齐,或是内存对齐到几个字节,以上面的结构体为例:
1)attribute ((aligned(4))) 对齐到4字节,同样可指定对齐到8字节,设置_attribute__ ((aligned(8)))。

{
    char name[7];
    uint32_t id;
    char subject[5];
} __attribute__ ((aligned(4))); 

2)attribute_ ((packed)) 不对齐,结构体的长度,就是各个变量长度的和

struct student
{
    char name[7];
    uint32_t id;
    char subject[5];
} __attribute__ ((packed));

在编写的c++程序中,如果是窗口,有时会一闪就消失了,如果不想让其消失,在程序中添加:
system(“pause”);//请按任意键继续
注意:不要再return 的语句之后加,那样就执行不到了。
分析:、
system()就是调用(DOS)系统命令(和shell命令)。
pause ,即DOS命令集合中的暂停命令;
在一个程序中写有 system(“pause”)语句时,就是说从该程序里调用了“pause”命令,即让操作系统来暂停该程序进程的执行,同时程序运行到此语句处时,会在程序的窗口上显示“Press any key to continue . . .” 也就是 “按任意键继续…”,即等待用户按下任意一个按键使该程序从暂停状态返回到执行状态继续从刚才暂停的地方开始执行。
说明:
void system(char *cmd);
参数cmd,DOS命令,如Pause, cls
返回值:无。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值