1.什么是对齐?为什么要对齐?
2.pragma pack语法
3.结构体对齐规则
3.1 基本数据类型所占内存大小
3.2 Test1
-
#pragma pack(4)
-
struct Test1
-
{
-
char c;
-
short sh;
-
int a;
-
float f;
-
int *p;
-
char *s;
-
double d;
-
};
总共占28Bytes。 c的偏移量为0,占1个Byte。sh占2个Byte,它的对齐模数是2(2<4,取小者),存放起始地址应该是2的整数倍,因此c后填充1个空字符,sh的起始地址是2。a占4个Byte,对齐模数是4,因此接在sh后存放即可,偏移量为4。f占4个字节,对齐模数是4,存放地址是4的整数倍,起始地址是8。p,s的起始地址分别是12,16。d占8个字节,对齐模数是4(4<8),d从偏移地址为20处存放。存放后结构体占28个字节,是4的整数倍不用补空字符。
-
struct Test2
-
{
-
char c;
-
double d;
-
int a;
-
short sh;
-
float f;
-
int *p;
-
char *s;
-
};
将Test1个变量的顺序换一下位置,结构体Test2占用内存32Byte,可见写结构体时,将各个变量按所占内存从小到大排列所占结构体所占内存较小。
3.3关于静态变量static
静态变量的存放位置与结构体实例的存储地址无关,是单独存放在静态数据区的,因此用siezof计算其大小时没有将静态成员所占的空间计算进来。
-
#pragma pack(4)
-
struct Test3
-
{
-
char c;
-
short sh;
-
int a;
-
float f;
-
int *p;
-
char *s;
-
double d;
-
static
double sb;
-
static
int sn;
-
};
sizeof(Test3)=28
3.4关于类
空类是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。
(一)类内部的成员变量:
(二)类内部的成员函数:
-
#pragma pack(4)
-
class cBase{};
3.4.1 不包含虚函数的类
-
#pragma pack(4)
-
class CBase1
-
{
-
private:
-
char c;
-
short sh;
-
int a;
-
public:
-
void fOut(){
cout <<
“hello” <<
endl; }
-
};
不包含虚函数时,对于类中的成员变量按结构体对齐方式处理,普通函数函数不占内存。sizeof(CBase1)=8
3.4.2 包含虚函数的类
-
#pragma pack(4)
-
class CBase2
-
{
-
private:
-
char c;
-
short sh;
-
int a;
-
public:
-
virtual void fOut(){
cout <<
“hello” <<
endl; }
-
};
包含虚函数时,类中需要保存虚函数表的入口地址指针,即需要多保存一个指针。这个值跟虚函数的个数多少没有关系。sizeof(CBase2)=123.4.3 子类
子类所占内存大小是父类+自身成员变量的值。特别注意的是,子类与父类共享同一个虚函数指针,因此当子类新声明一个虚函数时,不必在对其保存虚函数表指针入口。
-
#pragma pack(4)
-
class CBase2
-
{
-
private:
-
char c;
-
short sh;
-
int a;
-
public:
-
virtual void fOut(){
cout <<
“virtual 1” <<
endl; }
-
};
-
class cDerive :
public CBase
-
{
-
private :
-
int n;
-
public:
-
virtual void fPut(){
cout <<
“virtual 2”; }
-
};
sizeof(cDerive)= sizeof(cBase)+sizeof(int n) = 16