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

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

答案是: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 0
char b; //start address is 4
int c; //start address is 8
};
struct stru2
{
int i; //start address is 0
short m; //start address is 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
};

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;
}
运行结果:

————————————————
版权声明:本文为CSDN博主「海月汐辰」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37858386/article/details/75909852

sizeof()计算结构体的大小的更多相关文章

  1. sizeof操作符-结构体与类大小

    导读 sizeof是C/C++一个难点,当在自定义类上应用sizeof操作符时,总会出现意想不到的结果,下面,我们就来探讨一下sizeof这个操作符! 目录 1. sizeof与strlen的区别 2 ...

  2. C-sizeof和strlen区别,以及sizeof如何计算结构体大小

    sizeof和strlen区别 sizeof是关键字,在编译时就能计算出值,可以计算任何类型 strlen是函数,只有在运行时才能去计算,且只能计算字符型的. 对于数组时,strlen是判断’\0’为 ...

  3. 关于结构体占用空间大小总结(#pragma pack的使用)

    关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的.这道题是这样的: 在32位机器上,下面的代码中 class A { publi ...

  4. 【2017-07-01】Linux应用开发工程师面试问题记录之二:关于结构体的大小及内存对齐问题

    Tencent后台服务器开发有一道题是计算一个结构体的sizeof的大小: struct strData { int m_Int; char m_Char; short m_Short; char m ...

  5. sizeof(结构体) = ?

    关于结构体大小怎样计算的文章,我想网上一搜到处都有人总结,本人之所以在此基础上还要发表这样的文章是想用最简单的计算方法来总结前人给出的结论,以致我们在以后在对结构体相关编程中不会陷入字节对齐的陷阱中. ...

  6. 结构体(struct)大小

    结构体(struct)大小 本文参考链接:C语言结构体(struct)常见使用方法,链接中的实例代码经实践有几处不准确,本文在引用时已做更改 注意:在结构体定义时不能申请空间(除非是结构体变量),不可 ...

  7. YTU 2577: 小数计算——结构体

    2577: 小数计算--结构体 时间限制: 1 Sec  内存限制: 128 MB 提交: 978  解决: 647 题目描述 小数可以看成是一个点和两个数组成的,因此可以定义成一个小数的结构体,现在 ...

  8. sizeof求结构体大小

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  9. 计算结构体、数组、指针的sizeof

    1. 结构体的sizeof 题目: sturct aa{ in num; char name[10];}; struct bb{ int a; float b; struct aa c;}; stru ...

随机推荐

  1. LinuxShell——正则表达式

    LinuxShell——正则表达式 摘要:本文主要学习了Shell中的正则表达式. 简介 含义 正则表达式,也称作正规表示法,是用于描述字符排列和匹配模式的一种语法规则,它主要用于字符串的模式分割.匹 ...

  2. 剑指:和为S的两个数字

    题目描述 输入一个数组和一个数字 s,在数组中查找两个数,使得它们的和正好是 s. 如果有多对数字的和等于s,输出任意一对即可. 你可以认为每组输入中都至少含有一组满足条件的输出. 样例 输入:[1, ...

  3. 困扰了2天的问题,终于解决了。VB6的MSComCtl.ocx在32位Win7显示对象库未注册

    解决方案在这里,中文的资料真的挺垃圾的.(重启几次之后又不行了....怎么回事???) 安装.net framework4.0以上版本, C:\Windows\System32, C:\Windows ...

  4. Eric6 黑色风格配置

    界面风格-黑色主题 1.设置-首选项-界面-风格选择Fusion,再配置题样式表选择路径下的eric6\Styles选择[Chinese_Dark.qss]进行修改. ​ 编辑器风格 2.选择完毕后, ...

  5. 12、shell_awk

    AWK awk 是一个优良的文本处理工具,其名字来源于三个开发人员的名字首字母缩写. awk 不但是一个优良的文件处理工作,它还可以自己编程,编写awk 程序   AWK基本格式:      awk ...

  6. Linux CentOs基本命令

    基本操作(命令模式下) yy --复制光标所在行 nyy --n为数字,复制光标所在向下n行 p --粘贴到光标的下一行 P --贴在光标的上一行 G --光标移到文件末尾 gg --光标移到文件头 ...

  7. 语义分析的waf 目前就看到长亭 机器学习的waf有fortnet 阿里云的waf也算

    近期,在全球权威咨询机构 Gartner 发布的 2019 Web 应用防火墙魔力象限中,阿里云 Web 应用防火墙成功入围,是亚太地区唯一一家进入该魔力象限的厂商! Web 应用防火墙,简称 WAF ...

  8. linux open 黄色文件

    表示设备文件 生成的新的pdf

  9. webpack开发指南1

    怎么安装Webpack 安装node.js 首先需要安装Node.js,node自带了包管理工具npm. 安装webpack 使用npm install webpack -g,webpack全局安装到 ...

  10. web-天下武功唯快不破

    没有武术是不可摧毁的,而最快的速度是获得长期成功的唯一途径.>>>>>> ----你必须尽可能快地做到这一点!---- <<<<<&l ...