当前位置: 首页 > news >正文

C语言:结构体的大小

在C语言中,结构体(struct)是一种用户自定义的复合数据类型,它允许将不同类型的数据组合成一个整体,便于管理和操作。然而,结构体的内存分配并非简单的成员大小相加,而是涉及**内存对齐(Memory Alignment)**这一关键机制。本文将系统讲解结构体的定义、内存布局、大小计算方法,并深入分析内存对齐的原理与优化技巧。

一、结构体的基本概念

在探讨结构体的大小之前,先来简单回顾一下结构体的基本概念

结构体是C语言中用于组织相关数据的集合,其成员可以是任意类型(包括其他结构体)。例如:

struct Student { char name[20]; // 字符串 int age; // 整型 float score; // 浮点型 };

在这个例子中,我们定义了一个名为Student的结构体,它包含了三个成员:一个字符数组name用于存储学生的姓名,一个整型变量age用于存储学生的年龄,以及一个浮点型变量score用于存储学生的成绩。

定义好结构体后,我们可以声明结构体变量并对其进行初始化。例如:

struct Student stu1 = {"Tom", 20, 85.5};

结构体的访问有两种方法:成员访问和指针访问

1.成员访问:通过.运算符(如student.age

2.指针访问:若为结构体指针,使用->运算符(如p_student->age

二、结构体的大小

结构体的大小并不是简单地将其各个成员的大小相加,这是因为存在内存对齐的机制。内存对齐是为了提高内存访问的效率(用空间去换访问时间的效率),编译器会在结构体成员之间插入一些填充字节。

1.结构体内存对齐的规则--基本原理

① 第一个成员在与结构体变量偏移量为0的地址处。
② 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数= 编译器默认的一个对齐数 与该成员大小的较小值。VS中默认的值为8

后面的结构体大小的示例均是在VS中演示的
结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
④ 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

2.结构体大小计算演示
struct stu1 { //占用的字节号 char a; //1(对齐数) 0 (1)浪费 short b;//2 2 3 b的对齐数 short: 2 < 8 为2 int c; //4 4 5 6 7 该结构体的最大对齐数为 4 };//0~7共8个字节 8 % 4==0 满足 这个结构体大小为8个字节

简单解释一下,这里面a为一个字节,占用0号字节,但是b的对齐数为2,b之前所占用的字节数为1,1%2!=0,所以要对a后面再补充一个字节,逻辑上使a占用0 ,1号字节,这样b之前共占用2个字节,2%2==0,满足条件,b接着占2 ,3号字节,c的对齐数为4,c之前所占用字节数为4,4%4==0,c接着占用4 ,5,6,7号字节,8>4>2>1 所以该结构体的最大对齐数为4,大小就为8了.

struct stu2 {//各个成员的对齐数 所占字节编号 char a; //1 0 (1 2 3) int b; //4 4 5 6 7 short c; //2 8 9 (10 11) 该结构体的最大对齐数为4 };//0~9共10个字节 10%4!=0 因为 12%4==0 需再补两个字节 所以该结构体大小为12字节
struct stu3 { char a; //1 0 (1 2 3) float b; //4 4 5 6 7 double c; //8 8-15 int d; //4 16 17 18 19(20 21 22 23) long long e;//8 24-31 //0-31 32Byte 32%8==0 };

接下来一点一点提升难度,将详细展示结构体的大小计算:

含有数组的结构体:

​ //Type Name[Size] //对于含有数组成员的结构体,只需将其看作有Size个Type成员即可 将成员大小乘以Size即可 struct stu4 { char arr[9];//1 0-8 (9 10 11) int b; //4 12 13 14 15 short c; //2 16 17 (18 19 20 21 22 23) double d[2];//8 24 - 39 };//0-39 40 struct stu5 { char arr[11]; //1 0-10 (11 - 15) struct stu4 a;//8 16 - 55 long b; //4 56 57 58 59 float c; //4 60 61 62 63 short d[7]; //2 64 - 77 };//78 % 8!=0 80 ​

计算嵌套结构体的大小(结构体stu5和stu2均是上面计算过的结构体,后面引用均是):

struct stu6 { char c; //1 0 (1 2 3) int d[100]; //4 4-403 (404 - 407) struct stu5 arr[7]; //8 408 - 967 //stu5的最大对齐数为8,单个结构体的大小为80 结构体数组arr所占的总大小为560字节 //968%4==0 struct stu2 brr[21];//4 968 - 1219 //stu2的最大对齐数为4,单个结构体的大小为12 结构体数组arr所占的总大小为252字节 //1220%4==0 float e[11];//4 1220 - 1263 };//1264 % 8 ==0

嵌套结构体与指针结合:(读者若是对指针有疑惑可以参考我上篇有关指针的知识介绍,相信让你对指针会有更深的理解)

struct stu8 { char a; //1 0 1 short b; //2 2 3 int* c; //4 4-7 double* d; //4 8-11 //c,d均为指针,大小为四个字节 int arr[10]; //4 12 - 51 int(*brr)[10]; //4 52 53 54 55 //brr为一个由10个int成员构成的数组的地址 大小为4个字节 struct stu6* crr[10];//4 56 - 95 //crr 是一个有10个struct stu6* 类型元素构成的数组 crr的大小为40个字节 struct stu* drr; //4 96 97 98 99 //drr 为结构体指针 大小为4个字节 //因为 8 > 4 所以该结构体的最大对齐数为4 };//0~99 100个字节 100%4==0 所以该结构体的大小为100字节

在vs中将结果验证给读者:

3.拓展:修改默认对齐数

#pragma pack(n)//修改(设置)默认对齐数为指定的n

对齐数 = 该成员大小 与 默认对齐数比较的 较小值;而上述函数可以修改默认对齐数的大小

​ //不修改 struct stu9 {//成员对齐数 所占字节号 int a; //4 0 1 2 3 char b; //1 4 (5 6 7) double c;//8 8 --15 };//0~15 16个字节 16%8==0 该结构体的大小为16字节 //修改 #pragma pack(2) //修改(设置)默认对齐数为2 struct stu7 { //成员对齐数 所占字节号 int a; //2 0 1 2 3 char b; //1 4 (5) double c; //2 6 -- 13 c的大小虽然为8字节 但是与默认对齐数 };//0~13 14个字节 14%2==0 该结构体的大小为14字节 2比较要大,所以2是c成员的对齐数 ​

在vs中向读者演示:

三、总结

结构体是C语言中非常重要的一种数据类型,它允许我们将不同类型的数据组合在一起。在计算结构体大小时,需要考虑内存对齐的因素。通过合理调整结构体成员的顺序,可以优化结构体的空间使用。深入理解结构体及其大小计算,有助于我们编写更高效、更节省内存的C语言程序。

希望通过本文的介绍,读者对结构体和结构体大小计算有了更全面的理解,加油💪💪💪!!!

http://www.jsqmd.com/news/856968/

相关文章:

  • 多功能复合材料树状介孔硅的定制介绍
  • 番茄小说下载器:打造你的个人数字图书馆之旅
  • 梳理2026年环保节能的玉兰灯品牌,推荐哪家好 - mypinpai
  • 告别滚动混乱:Scroll Reverser让你在Mac上统一触控板和鼠标的滚动方向
  • 终极指南:30天重置JetBrains IDE试用期的完整解决方案
  • ADL 概念
  • OpenRPA实战手册:3步掌握免费企业级RPA自动化终极指南
  • FPGA设计避坑指南:别再乱用同步复位了,聊聊异步复位同步释放的实战配置
  • 从“它激”到“自激”:三引脚压电陶瓷片在低成本报警器设计中的妙用
  • Fansly Downloader:3分钟掌握离线收藏创作者内容的完整解决方案
  • 2026TOP5南昌市青云谱区黄金,白银,铂金回收门店推荐及联系方式权威发布 - 前途无量YY
  • Java数据结构——List接口与ArrayList源码剖析
  • 9 款论文查重 / 降 AIGC 工具横评:Paperxie 领衔,从查重到降 AIGC 一站式解决毕业焦虑
  • CTF Pwn新手必看:手把手教你用格式化字符串漏洞绕过PIE保护(附Python脚本)
  • 5个理由告诉你为什么ViGEmBus是Windows游戏控制器模拟的最佳选择
  • 用SystemVerilog的unique/priority优化你的case语句:告别Latch和优先级烦恼
  • Display Driver Uninstaller:彻底解决显卡驱动问题的专业工具指南
  • 千问 LeetCode 2478.完美分割的方案数 Python3实现
  • Linux head、tail 命令详解——查看文件首尾内容+实时监控日志(工作必备)
  • Java EE:2.多线程-初阶(第三弹)
  • NPS内网穿透实战:5分钟为你的本地开发环境(如SpringBoot、Vue)配置一个临时公网URL
  • 黔西南兴义西服定制优选:六大本土实力厂家深度盘点(附联系方式) - 贵州服装测评君
  • 抖音视频批量下载终极指南:免费无水印工具完整教程
  • 如何测量WIFI通讯中客户端的漫游时间
  • 【C++笔记】内存管理流食般投喂
  • 为什么Java老手都推荐装JDK 8?从版本选择到目录结构,一次给你讲明白
  • Scratch游戏避坑指南:为什么你的‘躲子弹’游戏卡顿?变量与克隆体管理的3个关键点
  • 新闻传播论文降AI工具免费推荐:2026年新闻传播毕业论文AIGC超标免费4.8元达标完整方案
  • 用Python和GDAL处理高分二号卫星遥感数据:从TIF读取到归一化的保姆级教程
  • 别再用math.atan了!用NumPy的angle函数处理复数相位,效率提升不止一点点