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

C语言、结构体

📚 目录

  • 1. 结构体类型声明定义
  • 2. 结构体的创建和初始化
  • 3. 结构体内存大小
  • 4. 结构体的传参
  • 5. 位段

前言:
C语言也给我们程序员规定了一种自定义类型,结构体的每一个成员可以是不同类型的变量,结构是⼀些值的集合,这些值称为成员变量,那么结构体的内存大小又是怎么算的呢?

1. 结构体类型声明定义

结构是⼀些值的集合,这些值称为成员变量;关键字:struct

#include<stdio.h>structadd//结构体的声明定义{inta;}value;//value指的是这个结构体的名字 旁边这个分号必须要添加 value可以先不写,等我们需要的时候创建就行了//比如intmain(){structadds1;//我们创建的时候就能够这么写return0;}

这就是简单的结构体声明
假设当我们想要描述一个学生的时候。

structstu{charname[20];intage;floatScore;};

这就简单创建了一个简单结构体类型。

🔙 返回目录




2. 结构体的创建和初始化

就拿我们的学生这个结构体来讲

#include<stdio.h>structstu//结构体声明定义{charname[20];intage;floatScore;};intmain(){//struct stu s1;这个是结构体的创建,类型位struct stu 名字位:s1//结构体的创建和初始化structstus1={"zhangsan",20,95.5f};//这就是我们简单的初始化,也可以部分初始化,或者不初始化。//当我们想不按照这个顺序初始化的时候我们就要用到这个操作符structstus2={.age=20,.Score=95.5f,.name="zhangsan"};return0;}
结构体的打印:
#include<stdio.h>structstu//结构体声明定义{charname[20];intage;floatScore;};intmain(){structstus2={.age=20,.Score=95.5f,.name="zhangsan"};//打印printf("%d\n",s2.age);printf("%f\n",s2.Score);printf("%s\n",s2.name);return0;}

结构的特殊声明:

比如:

//这样类型的特殊声明struct{charname[20];intage;floatscore;}value;//还有这样的结构体声明struct{charname[20];intage;floatscore;}value[10],*p;

这样的声明省略掉了我们结构体的名字,直接就创建了我们的变量。
那么这样做编译器会不会报错呢?
答案:不会报错
警告:

编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用一次。

结构体类型的自引用:

学到数据结构的时候我们就会知道链表这个概念。

就又没有想过,结构体里面包含结构体,一个连接着一个,形成一个链条一样的链表。
举例:

//就像这样写structNode{inta;structNode*next;};

以上就是我们的结构体的创建和初始化以及特殊的结构体声明定义。

🔙 返回目录




3. 结构体内存大小

那么结构体的内存大小又是怎么算的呢?
接下来我们来学习一下。

structstu{charname[20];intage;};

这个结构体内存大小多大呢?
答案:24
为什么是24呢?我们就要了解最大对齐数这个概念。
对其规则

最大对齐数:

结构体的第1个成员对齐到和结构体变量起始位置偏移量为0的地址处。
从第2个成员变量开始,都要对齐到某个对其数的整数倍的地址处,(对其数 = 编译器默认的⼀个对其数与该成员变量大小的较小值。)
结构体总大小为最大对齐数的整数倍。
嵌套了结构体的情况下,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构
体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

举例:
注意:每一个编译器默认的对齐数都是不一样的,就像我们Vs这个编译器默认的对齐数为:8

#include<stdio.h>structS1{charc1;//对齐数位1inti;//对齐数为4charc2;//对齐数为1};intmain(){printf("%zu\n",sizeof(structS1));//选择最大对齐数的整数倍return0;}


修改默认对齐数
#include<stdio.h>#pragampack(1);//设置默认对齐数为1structS{charc1;//对齐数位1,而我们默认对齐数为1 , 对齐数为1inti;//对齐数为4,而我们默认对齐数为1 , 对齐数为1charc2;//对齐数为1,而我们默认对齐数为1 , 对齐数为1};#pragmapack();取消修改默认对齐数intmain(){printf("%d\n",sizeof(structS));return0;}

得到的结果都是我们的1000。这样我们就能知道:结构体传参的时候,要传结构体的地址

🔙 返回目录



4.结构体的传参

结构体又是怎么传参的呢?

#include<stdio.h>structS{intdata[1000];intnum;};//结构体传参//测试传结构体voidtest1(structSs){printf("%d\n",s.num);}//测试地址voidtest2(structS*s){printf("%d\n",s->num);}intmain(){structSs={{1,2,3,4},1000};test1(s);//传结构体test2(&s);//传地址return0;}

得到的结果都是我们的1000。这样我们就能知道:结构体传参的时候,要传结构体的地址

🔙 返回目录



5.位段

什么是位段?
位段:
1. 位段的成员必须是int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他整型家族类型,比如:char。
2. 位段的成员名后边有⼀个冒号和⼀个数字。

举例:

structA{int_a:2;int_b:3;int_c:30;};intmain(){printf("%d\n",sizeof(structA));return0;}

这就是我们位段的写法。
A就是⼀个位段类型。

位段的内存分配:

1. 位段的成员可以是int、 unsigned int、signed int 或者是char 等类型
2.位段的空间上是按照需要4个字节或者一个字节的方式开辟
3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

例如:

#include<stdio.h>structS{chara:3;charb:4;charc:5;chard:4;};intmain(){structSs={0};s.a=10;s.b=12;s.c=3;s.d=4;return0;}


注意:
位段在跨平台的时候会出现问题。
问题:
int 这个位段被别的编译器当成有符号数还是无符号数是不确定的。
位段中最大位的数不能确定。
位段中的成员在内存中从左向右分配,还是从右向左分配
当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,无法容纳于第⼀个位段剩余的位时,是舍弃
剩余的位还是利用,这是不确定的。
总结:位段可以达到结构体那样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

🔙 返回目录



完!

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

相关文章:

  • Claude code底层实现原理(内存管理与并发)
  • C语言、自定义类型:联合体、枚举
  • DeepSeek LeetCode 699. 掉落的方块 public List<Integer> fallingSquares(int[][] positions)
  • GraphRAG开源生态全景:6大主流开源项目,微软/蚂蚁/港大项目同台PK
  • 软件综合项目笔记
  • 2026 最新解读:AI 在数字资产管理中的 5 大应用场景与实践路径
  • DeepSeek LeetCode 710. 黑名单中的随机数 public Solution(int n, int[] blacklist) Java实现
  • 个人笔记机器学习2
  • 70.爬楼梯
  • R ∪ S(并集)**:正确合并了 R 和 S 的所有元组,并去重((b,a,d) 和 (d,f,g) 在两者中均出现,只保留一次
  • 【ZooKeeper】 ZooKeeper面试必知必会:从基础到进阶的全方位指南
  • SEH详解(六)
  • PCIe-FC补充《PCI Express Technology 3.0》Chapter 6 Flow Control
  • Netty[ NIO 核心速成 ] ---- NIO三大组件(Channel Bufferselector)
  • AI赋能森林火防助力开启智慧守护新篇章,基于最新以注意力为核心的YOLOv12全系列【n/s/m/l/x】参数模型开发构建AI智能化森林火防无人机巡检场景下森林火点、烟雾异常检测预警系统
  • 走上管理岗,一定要学会立威
  • java工具:《Java字符串处理:如何获取指定字符第N次出现的位置?》
  • STM32 学习 —— 个人学习笔记9-1(USART串口协议 串口发送及接收数据)
  • 461.汉明距离
  • 附录A 游戏推广运营实战:《暗黑王朝》的市场化之路
  • GESP三级历年真题解析(原码、反码和补码)
  • leetcode 困难题 1402. Reducing Dishes 做菜顺序
  • 2026年热门的AI品牌管理品牌推荐:AI品牌管理系统/AI品牌营销管理系统实力公司推荐 - 品牌宣传支持者
  • leetcode 1405. Longest Happy String 最长快乐字符串-耗时100
  • 计算机毕设 java 梅州红色文化传承小程序 Java+SpringBoot 梅州红色文化小程序 微信小程序红色文化传承平台
  • 2026 独立开发者 AI 工具栈:我的选择和理由
  • 从交易者到“合伙人”:Cber经纪人体系全解析,你的每一份共识都算数
  • 5个免费IP查询API对比:哪个最适合你的项目?(附性能测试数据)
  • ChatTTS下载安装全攻略:从原理到避坑指南
  • 2026年知名的AI品牌视频公司推荐:AI品牌宣传片/AI品牌营销管理/AI品牌营销管理系统品牌公司推荐 - 品牌宣传支持者