struct,class的sizeof大小问题

来源:互联网 发布:java教程电子书下载 编辑:程序博客网 时间:2024/05/11 13:19

在32位机器上,下列代码中

class A  {       int i;       union U       {           char buff[13];           int i;       }u;       void foo() {    }       typedef char* (*f)(void*);       enum{red, green, blue} color;  }a; 

sizeof(a)的值是()

实例化class A
int i占4个字节
union U实例化为u占取16个字节(char数组占13个字节,但因为最大类型为int,所以占取只能为4字节的整数倍即最小16字节)
空函数不占取字节
未实例化指针不占取字节
枚举类型占取4个字节
总共占取4+16+4=24个字节

联合体
用途:使几个不同类型的变量共占一段内存(相互覆盖)
结构体是一种构造数据类型
用途:把不同类型的数据组合成一个整体——-自定义数据类型

结构体的内存分配:
结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐。
原则1 数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
原则2 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
原则3 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

联合的内存分配:
Union的大小为其内部所有变量的最大值,并且按照联合体中 类型 最大值的整数倍进行内存对齐:

union U      {          char buff[13];          int i;      }u;

首先按照char buff[13]分配13个字节,然后按照int的4个字节对齐,最终sizeof(u2)=16; (大于等于13且能被4整除的最小的数,即16)
根据原则2,u在class内要从u内部 类型最大的整数的倍开始储存,本题就是从4开始存16个字节。这时已经是4+16=20

成员函数不管是否为空,都不会占用空间,因为是this指针调用,有虚函数时除外,vtbl(virtual table)和vptr(virtual table pointer)会多出一个指针

typedef 是声明,枚举则是int 实现.20+4=24

结构体的大小

结构体计算要遵循字节对齐原则
结构体默认的字节对齐一般满足三个准则:

  • 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
  • 2)
    结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
  • 3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)

其实 暂且不管这三原则,我的方法只要记住第三个,就是结构体大小结果要为成员中最大字节的整数倍
这里写图片描述

输出结果是:

12

8

20

先看第一个结构体,第一个成员a的偏移量为0。第二个成员b的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员c的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。偏移量8加上最后一个成员c自身的大小,即为9,9不能被最宽基本类型成员大小整除,所以这里编译器会在最后补齐3个字节,得出12。

class A{        int a;        short b;        int c;        char d;};class B{        double a;        short b;        int c;        char d;};

根据以下条件进行计算:
1、 结构体的大小等于结构体内最大成员大小的整数倍
2、 结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍,比如说double型成员相对于结构体的首地址的地址偏移量应该是8的倍数。
3、 为了满足规则1和2编译器会在结构体成员之后进行字节填充!

A中,a占4个字节,b本应占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,为了满足条件1,d占用4个字节,一共16个字节。
B中,a占8个字节,b占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,
即abc共占用8+4+4=16个字节,
为了满足条件1,d将占用8个字节,一共24个字节。

原创粉丝点击