sizeof 变量占用内存,数组占用内存,结构体占用内存,类占用内存

前一段笔试一直考,一直不会做……前两天虎牙面试,问这个也不会,说是float占8个字节,对齐也完全不知道,就很尴尬……补一下吧,以后能记住也好……

一、各变量类型占用内存:

char:1个字节

wchar_t:2个字节

bool:1个字节

short:2个字节

int:4个字节

float:4个字节

double:8个字节

long long:8个字节

32位系统:

扫描二维码关注公众号,回复: 900675 查看本文章

long:4个字节

指针:4个字节

64位系统:

long:8个字节

指针:8个字节

unsigned不影响sizeof的取值。

对函数使用sizeof,再编译阶段会被函数返回值的类型取代,如int f1()会返回4,double f2()会返回8.

二、数组占用内存

数组大小就是各维数的乘积*数组元素的大小。

char a[] = "abcdef";  
int b[20] = {3, 4};  
char c[2][3] = {"aa", "bb"};  
  
cout<<sizeof(a)<<endl; // 7  
cout<<sizeof(b)<<endl; // 20*4=80  
cout<<sizeof(c)<<endl; // 6  

数组a的大小在定义时未指出,编译时分配给它的空间按照初始化的值确定,未元素个数加1,为7;

b为分配的20个元素*4=80;

c为2*3=6

看这一段程序:

int *d = new int[10];
cout << sizeof(d) << endl;

d是动态数组,它实质上是一个指针,所以sizeof(d)的值为4.

三、结构体占用内存

对齐:

 现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐

用空间换时间,会出现空闲空间浪费的情况。

 结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则:

     1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

     2) 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

     3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

例1:

结构体定义如下:

struct A

{

    char a;

    short b;

    int c;

};

a占用一个字节之后,为使b满足2要求,需要再a之后填充一个字节。总的占用为8字节内存。

C语言字节对齐(以32位系统为例)

例2:

结构体定义如下:

struct A

{

   short b;

   int c;

   char a;

};

为了使c满足第二条准则,需要在给b填充两个字节之后再次填充两个字节。同时为了满足第三条准则,需要在给a填充一个字节之后再在后方填充三个字节。总占用内存为12个字节。

C语言字节对齐(以32位系统为例)

例3:

结构体定义如下:

typedef struct

{

   char a;

   short b;

   char c;

   int d;

   char e[3];

}T_Test;

sizeof(T_Test)为16;

char a占用1个字节,

short b占用2个字节,在a与b之间填充1个字节

char c占用1个字节

int d占用4个字节,在c与d之间填充3个字节

char e[3]占用3个字节,之后补充1个字节,

sizeof(T_Test)共16个字节。

例4:

有指定时其对齐的规则是:每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐,并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。

程序如下:

#pragma pack(2) //指定按2字节对齐

struct C

{

   char b;

   int a;

   short c;

};

#pragma pack() //取消指定对齐,恢复缺省对齐

分析:

b占用1个字节

a占用4个字节,大于2,分成两个3字节,在b与a之间填充1个字节,c占用2个字节,一共8个字节。

sizeof(struct C) = 8.


添加一个后来看到的结构体里嵌套结构体的sizeof大小求解问题:

struct stu
{
	int i;
	struct
	{
		char c;
		int j;
	}ss;
	int k;
};
cout << sizeof(stu) << endl;

这段程序运行结果为16,求最大的类型占用空间时,将嵌套的struct结构体ss展开了,最大为int占用的4位,

但是内部嵌套的struct结构体在计算空间时不与外部元素相合并。所以总的大小为:4+4+4+4=16.

再看一个嵌套结构体的例子:

struct stu
{
	char i;
	struct
	{
		char c;
		int j;
	}ss;
	char a;
	char b;
	char d;
	char e;
	char f;
};
cout << sizeof(stu) << endl;

这段程序运行的结果为20,最大为int占4位,第一个char i占4位,ss内char c占4位,int j占4位,

a,b,d,e占4位,f占4位,一共占20位没毛病。

再看一个嵌套数组的例子:

struct stu
{
	float f;
	char p;
	int adf[3];
};
cout << sizeof(stu) << endl;

输出结果为20,同嵌套结构体一样,确定最大占用空间类型时将数组拆分开,而不是用整个数组占用空间大小作为标准,

所以最大为int或float的4位,4+4+4*3=20。

四、类占用内存

1.

sizeof空类大小为1.

2.

class A
{
public:
        int a;
private:
	char b;
};
cout << sizeof(A) << endl;

简单类和求结构体的sizeof一样,考虑偏移和对齐,结果为8.

3.带虚函数的类

class A
{
public:
	int a;
	virtual void f() {}
};
cout << sizeof(A) << endl;

虚函数放在虚表中,类中定义了虚函数,需要存放一个指向虚表的指针。

sizeof(A)=sizeof(A.a)+sizeof(指针)=4+4=8;(指针在32位系统为4位)。

当存在多个虚函数时,仍然只需要一个指向虚表的指针:

class A
{
public:
	int a;
	virtual void f() {}
	virtual void f1() {}
	virtual void f2() {}
};
cout << sizeof(A) << endl;

结果仍然为8.

4.继承的类

普通继承的空间计算结果是sizeof(基类)+sizeof(派生类)。对齐考虑的是所有类中占用空间最大的数据类型。

class A {
public:
	int a;
	char b;
};
class B:public A
{
	char c;
};
cout << sizeof(B) << endl;

结果取决于编译器,vs中结果为12,说明将char b和char c是分开的,4+4+4=12.

class A
{
public:
	int a;
};
class C :public A
{
public:
	int c;
	double e;
};
cout << sizeof(C) << endl;

但是到这里结果又变成了16了,这不就是将a和c合并在一个8的空间了吗?按照上一个例子,a和c应该各自占用8个空间呀……不是很懂,有点玄学……

class A {
public:
	int a;
	virtual void get() {}
};
class B:public A
{
public:
	int c;
	virtual void set() {}
};
cout << sizeof(B) << endl;

基类和继承类中均包含虚函数时,同样只存放于一个虚表中,因此只需要一个指针,所以结果是4+4+4=12.

多重继承的情况:

class A
{
public:
	int a;
};
class B :public A
{
public:
	int b;
};
class C :public A
{
public:
	int c;
};
class D :public B, public C
{
public:
	int d;
};
cout << sizeof(D) << endl;
sizeof(D)=sizeof(B)+sizeof(C)=(4+4)+(4+4)+4=20

五、其他

union的sizeof:

union u
{
	double a;
	int b;
};
union u1
{
	char a[13];
	int b;
};
union u2
{
	char a[13];
	char b;
};
cout << sizeof(u) << endl;
cout << sizeof(u1) << endl;
cout << sizeof(u2) << endl;

结果为8,16,13.

解析:

union的大小取决于它所有的成员中,占用空间最大的一个成员的大小。

u中最大的成员就是double a,sizeof(u)=8.

u1中占用最大的是char[13],但是需要与int对齐,所以最大为16.

u2占用最大的是char[13],所以为13.



部分参考于:点击打开链接

点击打开链接

猜你喜欢

转载自blog.csdn.net/n1neding/article/details/80202103