C/C++ - 字节对齐

C++字节自然对齐

C的字节对齐和C++基本相同,但是也有一些区别,在下面的分析中会有提及。

示例

#include <stdio.h>

class a{
};

class b{
	char b;
};

class c{
	char a;
	char b;
	char c;
	char d;
	char e;
};

class d{
	short a;
	char b;
};

class e{
	int a;
	short b;
	char c;
};

class f{
	static int a;
	char b;
};

class g{
	char a;
	char b;
	char c;
	short d;
	char e;
};

class h{
	class g g1;
	char a;
};

class i{
	class g g1;
	int a;
};

int main(int argv, char** argc){
	printf("class a size : %d\n", sizeof(a));
	printf("class b size : %d\n", sizeof(b));
	printf("class c size : %d\n", sizeof(c));
	printf("class d size : %d\n", sizeof(d));
	printf("class e size : %d\n", sizeof(e));
	printf("class f size : %d\n", sizeof(f));
	printf("class g size : %d\n", sizeof(g));
	printf("class h size : %d\n", sizeof(h));
	printf("class i size : %d\n", sizeof(i));
}


结果

在G++编译器如下:

class a size : 1
class b size : 1
class c size : 5
class d size : 4
class e size : 8
class f size : 1
class g size : 8
class h size : 10
class i size : 12

结论

1. 如Class a,C++的struct或者class为空,那么字节是1,编译器自动添加了一个字节,为了保证该类型的两个对象在内存上地址是不一样的,这个和C是不一样的,C的空struct是0;

2. 对齐大小为其中类型大小最大的类型为准,但是不会超过4字节(在32位机,以int为准),所以,Class b和c的最大类型是char,所以他们的对齐大小是1(char是1);Class d最大类型是short(是2),所以对齐大小是2;Class e最大类型是int(4),所以对齐大小是4,但是为什么不是12(int、short、char各占4)呢,因为局部对齐方式又会以1或者2为对齐大小(取1或2主要看其中是否存在2的类型,否则取1、结构体的每一个成员起始地址必须是自身类型大小的整数倍),但是总长度为4的倍数;

3. 对齐大小不超过4(32位机),所以如

class d{
	long long a;
	char b;
};
字节大小是12,而不是16,但是VC上结果是16;
4. static成员不属于对象,所以Class f的大小不包括static int a;

5. 如果存在嵌套关系,对齐大小以基本类型为准,如Class g、h、i,所以h以2(short)为对齐方式,i以4(int)为对齐方式,但是被嵌套类g在嵌套类中的内存是独立的,所以h的大小是10(|char|char|char|padding|short|char|padding|char|padding|)而不是8(|char|char|char|padding|short|char|char|);


C++字节强制对齐

还可以强制设置对齐大小

#pragma pack (size) //size可以取1/2/4/8等2的指数
struct c

char b; 
int a; 
short c; 
}; 
#pragma pack ()

struct c大小分别为7、8、12、12


紧缩方式

紧缩方式其实就是按1字节对齐,和#pragma pack (1) 效果一样。

为了防止不同编译器对齐不一样,建议在代码里面指定对齐参数。

可能重要的一点是关于紧缩结构的。紧缩结构的用途 其实最常用的结构对齐选项就是:默认对齐和紧缩。在两个程序,或者两个平台之间传递数据时,我们通常会将数据结构设置为紧缩的。这样不仅可以减小通信量,还可以避免对齐带来的麻烦。假设甲乙双方进行跨平台通信,甲方使用了“/Zp2”这么奇怪的对齐选项,而乙方的编译器不支持这种对齐方式,那么乙方就可以理解什么叫欲哭无泪了。 当我们需要一个字节一个字节访问结构数据时,我们通常都会希望结构是紧缩的,这样就不必考虑哪个字节是填充字节了。我们把数据保存到非易失设备时,通常也会采用紧缩结构,既减小存储量,也方便其它程序读出。各编译器都支持结构的紧缩,即连续排列结构的各成员变量,各成员变量之间没有任何填充字节。这时,结构的大小等于各成员变量大小的和。紧缩结构的变量可以放在1n边界,即任意地址边界。

如G++代码

class __attribute__ ((packed)) c

char b; 
int a; 
short c; 
}; 

class c的大小为7,即按1字节对齐。


位域

它可以指定每个成员占据的bit数,由于移植性不好(每个编译器处理都不太一样),所以能不使用就不要使用,在这也不做具体分析了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值