sizeof的理解

有一个求类型所占几字节这个问题经常反复出现,这里我决定深入的研究一下

 

先简单入手

Sizeof(char) = 1;

Sizeof(bool) =1;

Sizeof(double)= 8;

Sizeof(float) =4;

Sizeof(int) =4;

基本类型就这些。这些是不能出错的。

深入一层:

大家都知道编译器会对它进行优化。

如果我们在win32默认情况下 在vs2005编译器。

默认情况下先说两个规程

1.      类型的大小是:类型包含的基本类型中最大的整数倍。如下: sizeof(A)的大小是最大基本类型 double(8)的整数倍。

2.      每个基本类型的偏移地址必须是类型大小的整数倍。例如 int的偏移量必须是 0,4,8,12,16,….. double 的偏移量必须是0,8,16,24,32.

一.class A {

   int a;

   bool b;

   char c;

   double d;

};

 

a

a

a

a

b

c

填充

填充

d

d

d

d

D

d

d

d

sizeof(A)=sizeof(int)+sizeof(bool)+sizeof(char)+2+sizeof(double = 16

二. class A {

   char c;

   double d;

   int a;

bool b;

};

c

填充

填充

填充

填充

填充

填充

填充

d

d

d

d

d

d

d

d

a

a

a

a

b

填充

填充

填充

sizeof(A)=sizeof(char)+7+sizeof(doulbe)+sizeof(int)+sizeof(bool)+ 3 = 24.  24是double 的整数倍。 所以24是最终结果。

 

再看一个例子:

三. Class A{

 Chara;

Double b;

Int c;

};

a

填充

填充

填充

填充

填充

填充

填充

b

b

b

b

b

b

b

b

c

c

c

c

填充

填充

填充

填充

 

sizeof(A)=sizeof(char)+7+sizeof(doulbe)+sizeof(int) = 20   20不是double 的整数倍,所以还得填充4个。 所以24是最终结果。

 

我们再深入一下

四. class CA

{

   char a;

   double  b;

   int c;

};

这个我们好理解。 sizeof(CA)=sizeof(char)+7+sizeof(doulbe)+sizeof(int) + 4 = 24

 

class CB {

char ch;

   CA ca;

int ib;

}; 

Sizeof(CB)的大小,就稍微有点麻烦了。在类成员为止的时候必须是类中最大的整数倍。 Sizeof(char)+ sizeof(CA)= 1+24 =25 不是CA当中最大类型的整数倍(最大是8)需要填充7个。所以 为 1+7+24 + sizeof(int) = 36。 36不是8的整数倍,又需要填充4个,所以最终结果是40.

Ch

填充

填充

填充

填充

填充

填充

填充

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

Ca的部分

ib

ib

ib

ib

填充

填充

填充

填充

 

五.我们再深入一下

 

union u
{
 double a;
 int b;
};

union u2
{
 char a[13];
 int b;
};

union u3
{
 char a[13];
 char b;
};

cout<<sizeof(u)<<endl; // 8
cout<<sizeof(u2)<<endl; // 16
cout<<sizeof(u3)<<endl; // 13

 

 都知道union的大小取决于它所有的成员中,占用空间最大的一个成员的大小。所以对于u来说,大小就是最大的double类型成员a了,所以sizeof(u)=sizeof(double)=8。但是对于u2和u3,最大的空间都是char[13]类型的数组,为什么u3的大小是13,而u2是16呢?关键在于u2中的成员int b。由于int类型成员的存在,使u2的对齐方式变成4,也就是说,u2的大小必须在4的对界上,所以占用的空间变成了16(最接近13的对界)。

 

在深入一点点:

union un

{

   int a;

   char b[5];

};

 

class CA

{

   char a;

   un b;

};

 

Sizeof(un) = 8;

所以 sizeof(CA) = 1+8 = 9 .因为9不是int的整数倍,需要填充3个。 所以最后是12.

 

再举一个例子:

union un

{

   double a;

   char b[9];

};

 

class CA

{

   char a;

   un b;

};

 

Sizeof(un) = 16;

所以 sizeof(CA) = 1 + 16 =17。 17不是double的整数倍,需要填充7个。所以最后是24.

 

在学习 #pragmapack(n)的问题。

这里的n必须是2的幂级,也就是 n必须是1,2,4,8,16,32……,如果n不是上面的值,会提示warning,并且当成默认处理。

 

 

#pragma pack(1) // 就是一字节对齐。这个是比较清楚的。 把所有成员的大小累积起来就没问题了。例子如下

#pragma  pack(1)

class A {

   int a;

   bool b;

   char c;

   double d;

};

 sizeof(A)=sizeof(int)+sizeof(bool)+sizeof(char)+sizeof(double;

sizeof(A) = 4+ 1+ 1 +8  = 14 . 呵呵,这是没问题的。

 

好了,今天就写到这里欢迎大家指正。谢谢。


Ps:需要着重理解的就是两条,再强调一遍。王雪刚看好了。

1. 每种类型的排列位置的偏移量必须是它的整数倍。 

             例如 class A{ char a, double b;}; 先对 char a排列,因为a的大小是1, 0是1的整数倍,所以没问题,第一个位置就是放着char a。(另外说一句0是任何数的整数倍,类当中的第一个成员都可以直接放置) 放完a之后,编译量变成了1,1不是8(double)的整数倍,所以需要填充7个,编译量成8的倍数之后,才可以放置double b;

         加入 class B { double b, char a;}; 偏移量0是8的整数倍,所以直接放置double b没问题,然后编译量变成了8,8是size(char)的整数倍,所以直接放置char 啊;


2. 在前面的基础上放好之后,再判断总和是不是类中最大类型的整数倍。 sizeof(A) = 1 +7 + 8 = 16, 16是double的整数倍,所以最终结果就是16;

 sizeof(B) = 8 +1 = 9; 9 不是 double的整数倍所以要填充 填充 到是double的整数倍。9+7= 16; 所以最终解决就是16的整数倍。 


 其实就这两条结论。再复杂的情况也遵守这两条。


还有枚举类型,枚举类型的大小就是4. 所以枚举比较简单,易操作。就不再对枚举再详细举例了。

  

 再有就是在类中有Static类型的变量,这个就不属于我说范围之内了,这个的看C++基础了,了解Static类型的成员是由所以的对象共用一份就知道Static类型不包含在类中了。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值