C++中gcc __attribute__(packed)和__attribute__(aligned)

GCC支持用__attribute__为变量、类型、函数、标签制定特殊属性。这些不是编程语言的标准内容,属于编译器对语言的扩展

语法格式

__attribute__的语法格式为, 其位置约束放在尾部声明”;“之前

__attribute__((attribute_list))

aligned

aligned属性最常用在变量上,它的作用是告诉gcc, 为变量分配内存时,要分配在对其的内存地址上。一般的计算机内存是以字节(byte = 8bit)为最小单元。内存地址相当于从0开始的字节偏移数。如果一个内存地址是N的倍数,我们就说它是N字节对齐的(N-byte aligned)
对于C/C++中的基本数据类型,假设它的长度为n字节,那么该类型变量会被编译器默认分配到n字节对齐的内存上
例如:char的长度是1字节,char类型变量的地址将是1字节对齐的。int的长度是4字节,所有int类型变量将分配到4字节对齐的地址上。
这种默认情况下的变量对齐方式称为自然对齐。编译器之所以希望默认变量自动对齐,是因为对齐的情况下内存访问是最高效的 但有时我们希望改变这种默认长度,可以是以aligned属性

int x __attribute__((aligned(16)) = 0; 
//告诉编译器把变量分配在16字节对齐的内存地址上,而非默认的4字节

aligned不仅可以用作变量属性,还能用作函数属性和数据类型属性。它作为函数属性时的作用等价于对函数使用-falign-functions这个优化选项, 当它用作数据类型时,相当于告诉编译器,这一类型的所有变量都要按照指定字节数对齐。
还可以将aligned用于结构体

struct __attribute__ ((aligned(8))) my_struct1 {
	short f[3];
};

这么做不仅会影响该结构体变量分配的内存位置,还可能影响其占用。上面这个结构体有个长度为3的short数组,占用6个字节的内存,但由于指定了8字节对齐,编译器在结构体尾部额外填充2个字节。所以这个结构体大小为8字节。
对于结构体的内存大小和成员变量存储地址,可以查看https://www.cnblogs.com/xieyajie/p/8094788.html
但是align只能增加对齐字节数而不能减少,看下面的例子

struct __attribute__ ((aligned(4))) my_struct2 {
	short f[3];
};

虽然指定了4字节,但是结构体本身有6字节,最终还是会按照8字节对齐处理(自动弹出,保证8字节对齐)

packed

__attribute__((packed))的作用是告诉编译器取消结构体在编译过程中的优化对齐, 是GCC特有的语法,这个功能跟编译器有关。gcc编译器不是紧凑模式的,而tc模式是紧凑模式的

  • 在tc下
    struct test { char ch; int a; }; sizeof(int) =2; sizeof(test) = 3 紧凑模式

  • 在gcc下
    struct test { char ch; int a; }; sizeof(int) =4; sizeof(test) = 8 非紧凑模式

  • 在gcc下
    struct test { char ch; int a; }; sizeof(int) =4; sizeof(test) = 5 紧凑模式

使用packed属性可以节省内存,但是会造成非对齐内存访问。例如下面的结构体test的成员变量i, 它的内存地址不是4的倍数, 访问它就是非对齐访问。当使用.或者->操作符存取结构体成员时, 编译器会保证取到正确的值; 但是如果使用指针直接访问非对齐成员变量,就只能指望处理器非对齐访问了,否则会出错。 这也是很多人认为给结构体指定packed属性不太安全的原因

struct __attribute__ ((packed)) test {
	char ch;
	int i;
};
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值