原文链接:sizeof()计算结构体的大小_海月汐辰-CSDN博客_结构体的sizeof怎么计算

简要说明:结构体成员按照定义时的顺序依次存储在连续的内存空间,但是结构体的大小并不是简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统在存储结构体变量时的地址对齐问题。

一、没有成员的结构体占用的空间是多少个字节?

答案是:1个字节。

这就是实例化的原因(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类或空结构体(C++中结构体也可看为类)隐含的加一个字节,这样空类或空结构体在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。

二、首先介绍一个相关的概念——偏移量

struct stru 
         {  
                    int a;  //start address is 0
                   char b;  //start address is 4
                   int c;  //start address is 8
         };

偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。比如上面的结构体,第一个成员a的偏移量为0。第二个成员b的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员c的偏移量是第二个成员的偏移量应该是加上第二个成员的大小(4+1)。

三、在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)

(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

例子1:
struct stru1  
{  
     int a;  //start address is 0
     char b;  //start address is 4
     int c;  //start address is 8
};

PS:用sizeof求该结构体的大小,发现值为12。int占4个字节,char占1个字节,结果应该是9个字节才对啊,为什么呢?这个例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。

例子2:

struct stru2  
{  
      int i;  //start address is 0
      short m;  //start address is 4
};

PS:成员i的偏移量为0;成员m的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员m大小的整数倍。因此,编译器会在成员m后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。

例子3、4:

struct stru3  
{   
       char i;  //start address is 0 
       int m;   //start address is 4
       char n;  //start address is 8
};  
struct stru4  
{  
       char i;  //start address is 0
       char n;  //start address is 1
       int m;  //start address is 4
 };

虽然结构体stru3和stru4中成员都一样,但sizeof(struct stru3)的值为12而sizeof(struct stru4)的值为8。

由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。

四、 对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
       (1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。

(2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

例子1:

struct stru5  
{  
      short i;  
      struct   
      {  
           char c;  
           int j;  
      } tt;   
      int k;  
};

结构体stru5的成员tt.c的偏移量应该是4,而不是2。整个结构体大小应该是16。

例子2:

struct stru6  
{  
      char i;  
      struct   
      {  
           char c;  
           int j;  
      } tt;   
      char a;  
      char b;  
      char d;  
      char e;  
      int f;  
};

结构体tt单独计算占用空间为8,而stru6的sizeof则是20,不是8的整数倍,这说明在计算sizeof(stru6)时,将嵌套的结构体ss展开了,这样stu6中最大的成员为tt.j,占用4个字节,20为4的整数倍。如果将tt当做一个整体,结果应该是24了。

五:另一个特殊的例子是结构体中包含数组,其sizeof应当和处理嵌套结构体一样,将其展开,如下例子:

struct array  
{  
    float f;  
    char p;  
    int  arr[3];  
};

其值为20。float占4个字节,到char p时偏移量为4,p占一个字节,到int arr[3]时偏移量为5,扩展为int的整数倍,而非int arr[3]的整数倍,这样偏移量变为8,而不是12。结果是8+12=20,是最大成员float或int的大小的整数倍。

测试环境:vc++6.0

测试代码:

//#ifndef __cplusplus//#endif#include <iostream>
#include "stdio.h"
#include <stdlib.h>
using namespace std;struct stru_empty
{};
struct stru1
{  int a;  //start address is 0char b;  //start address is 4int c;  //start address is 8
};
struct stru2
{  int i;  //start address is 0short m;  //start address is 4
};
struct stru3
{   char i;  //start address is 0 int m;   //start address is 4char n;  //start address is 8
};
struct stru4
{  char i;  //start address is 0char n;  //start address is 1int m;  //start address is 4};struct stru5
{  short i;  struct   {  char c;  int j;  } ss;   int k;
};
struct stru6
{  char i;  struct   {  char c;  int j;  } tt;   char a;  char b;  char d;  char e;  int f;
};
struct stru7
{  char i;  struct   {  char c;  //int j;  } tt;   char a;  char b;  char d;  char e;  int f;
};
struct array
{  float f;  char p;  int  arr[3];
};
int main()
{ struct    stru6 st6;struct    stru7 st7;struct array ar;printf("sizof(char)=%d \n",sizeof(char));printf("sizof(int)=%d \n",sizeof(int));printf("sizof(short int)=%d \n",sizeof(short int));printf("sizof(long int)=%d \n",sizeof(long int));printf("sizof(long)=%d \n",sizeof(long));printf("sizof(float)=%d \n\n",sizeof(float));printf("sizof(stru_empty)=%d \n",sizeof(stru_empty));printf("sizof(stru1)=%d \n\n",sizeof(stru1));printf("sizof(stru2)=%d \n\n",sizeof(stru2));printf("sizof(stru3)=%d \n\n",sizeof(stru3));printf("sizof(stru4)=%d \n\n",sizeof(stru4));printf("sizof(stru5)=%d \n\n",sizeof(stru5));printf("sizof(stru6)=%d \n",sizeof(stru6)); printf("sizof(stru6.tt)=%d \n",sizeof(st6.tt));printf("the address of stru6.i=%d \n",&st6.i);printf("the address of stru6.a=%d \n\n",&st6.a);printf("sizof(stru7)=%d \n",sizeof(stru7));printf("sizof(stru7)=%d \n",sizeof(st7.tt));printf("the address of stru7.i=%d \n",&st7.i);printf("the address of stru7.a=%d \n\n",&st7.a);printf("sizof(ar)=%d \n",sizeof(ar));printf("sizof(ar.f)=%d \n",sizeof(ar.f));printf("sizof(ar.arr)=%d \n",sizeof(ar.arr));return 0;
}

运行结果:

sizeof()计算结构体的大小相关推荐

  1. 使用sizeof()计算结构体大小

    下面代码的输出结果是: #include <iostream> using namespace std; #pragma pack(4) struct T{ char a; short b ...

  2. C语言sizeof求结构体的大小

    运算符sizeof可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1; sizeof(int) = 4.基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小. ...

  3. sizeof计算结构体长度

    sizeof()是一种内存容量度量函数,计算数据(数组.变量.类型.结构体等)所占空间,用字节数表示. sizeof在计算变量所占的空间大小时所选取的机制: 1.结构体满足的三个条件 结构体的大小等于 ...

  4. 结构体PLUS(计算结构体类型大小及位段)~~

    如何计算结构体类型大小呢? 1. 结构体内存对齐 为什么要内存对齐呢? 2.修改默认对齐数 3.位段 什么是位段 位段的内存分配 位段的跨平台问题 位段的应用 关于结构体类型,之前阿涛写过一篇文章,里 ...

  5. C语言的sizeof运算符计算结构体大小

    C语言的sizeof运算符运算规则 sizeof运算符 **sizeof 是一个运算符,不是函数(方法).** 例子: 当想打印一个变量的存储区域大小时,可以直接写 int a = 5; printf ...

  6. 【C语言】一文搞定如何计算结构体的大小----结构体内存对齐规则

    要搞定如何正确地计算一个结构体的大小,我们就要深刻理解结构体内存对齐规则: 结构体内存对齐规则: 1.结构体的第一个成员永远在结构体起始位置偏移量为0的位置: 2.结构体成员从第二个成员开始,总是放在 ...

  7. C++ sizeof(struct)计算结构体大小

    一.sizeof() 在学习C++的时候会学到一个sizeof操作符,在 C 语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符.单位是位(byte). 我们都知道char.short ...

  8. C语言 计算结构体大小

    本文主要参考:结构体内存对齐(如何计算结构体的大小) 前言 数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数. 结构体中的成员可以是不同的数据类型, ...

  9. 第10章结构体01——结构体字节大小的计算

    1.该篇笔记详见C提高笔记(传智播客) 文章目录 博文01:(常考面试题) 三步解决C语言中struct字节对齐问题,结构体的字节大小问题 第1步.先确定结构体实际对齐单位, 第2步.除结构体的第一个 ...

最新文章

  1. [推荐] 创业者要留意优先清算权
  2. Java中设计模式之单例设计模式-1
  3. php asp 语法,ASP 语法
  4. ssh(Spring+Spring mvc+hibernate)——DeptServiceImpl.java
  5. 怎么调整计算机显示屏,电脑显示器怎样调大屏幕
  6. 基于JavaScript实现网页计算器
  7. ORA-06413 连接未打开的处理办法【独家办法】
  8. sphinx的使用1-创建索引
  9. 【数据产品案例】阿里生意参谋-用户分析
  10. 如何面试大厂web前端?(沟通软技能总结)
  11. python面向对象编程指南([美stevenflott_Python面向对象编程指南 ([美]StevenFLott洛特) 中文_IT教程网...
  12. 交大『云观CD-ROMIII』直接由CD-ROM执行之安装法(转)
  13. 搜索引擎推广公司引擎推广方法及技巧
  14. Web课程设计高校物资管理系统
  15. 报错: Called “net usershare info“ but it failed
  16. 2023年天津医科大学药学考研考情与难度、参考书及上岸前辈经验
  17. 景观生态学原理| 2 景观生态学的理论与核心
  18. 骗子不可怕,就怕骗子有文化
  19. 国科大学习资料--模式识别与机器学习(黄庆明)--期末复习题3(含答案)
  20. ae导出gif插件_GifGun插件|Aescaripts GifGun(ae输出gif插件)下载v1.7.7免费版 - 欧普软件下载...

热门文章

  1. Spring-boot中读取config配置文件的两种方式
  2. Eclipse for android 中设置java和xml代码提示功能(转)
  3. UIImage 压缩
  4. asp.net 时间显示格式
  5. python天气预报的功能介绍_python实现智能语音天气预报
  6. puppet 安装mysql_Puppet安装dashboard
  7. mysql workbench启动_怎么启动mysql workbench
  8. amoeba mysql读写分离_Mysql 实现读写分离的详细教程(amoeba)
  9. java svn 版本号_eclipse中的Java文件自动根据svn版本号生成注释
  10. 怎么查看MySQL 源码编译了什么_Mysql 源码编译教程贴