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

新号别搞:结构体+联合体+枚举


1、 联合体 (Union)


  • 使用union关键字。
  • 编译器只为最大的成员分配足够的内存空间。
  • 所有成员共用同一块内存空间,它们的起始地址是相同的。
  • 特性:给其中一个成员赋值,其他成员的值也会跟着变化。

1.1 大小计算规则

  • 联合的大小至少是最大成员的大小。
  • 对齐规则:当最大成员大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍。

1.2 大小端判断

int check() { int i = 1; // 在内存中存储为 00 00 00 01 if (*(char*)&i == 1) // 取低地址的一个字节 return 1; // 小端 else return 0; // 大端 }

小端模式:低位字节存放在低地址。所以取出第一个字节就是 01
大端模式:高位字节存放在低地址。所以取出第一个字节就是 00


1.3相同成员的结构体和联合体对比


2、枚举


2.1 声明

enum Color { RED, GREEN, BLUE };枚举顾名思义就是⼀⼀列举


2.2 默认值

0开始,依次递增 1(即 RED=0, GREEN=1, BLUE=2)。当然也可以手动赋值。


2.3 枚举的优点

  • 增加代码的可读性和可维护性
  • 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
  • 便于调试,预处理阶段会删除 #define 定义的符号
  • 使⽤⽅便,⼀次可以定义多个常量
  • 枚举常量遵循作⽤域规则,枚举声明在函数内,只能在函数内使⽤

2.4 举例

enum Color//颜⾊ { RED, GREEN, BLUE };

{}中的内容是枚举类型的可能取值,也叫 枚举常量 。取值都是有值的,默认从0开始,依次递增。


3、结构体 (Struct)


3.1 结构体类型的声明与初始化

基本语法struct tag { member-list; } variable-list;

3.1.1 结构体变量的创建和初始化

struct Stu { char name[20];//名字 int age;//年龄 }; int main() { //按照结构体成员的顺序初始化 struct Stu s = { "张三", 20, "男", "20230818001" }; printf("name: %s\n", s.name); printf("age : %d\n", s.age); }

3.1.2 特殊声明

  • 匿名结构体:省略标签名,通常用于只定义一次的情况。
  • 自引用:结构体内部包含指向同类型结构体的指针.

3.1.3 定义结构体不要使⽤匿名结构体

typedef struct Node { int data; struct Node* next; }Node;

3.2 结构体内存对齐

01. 结构体的第1个成员对⻬到和结构体变量起始位置偏移量为0的地址处
02. 从第2个成员变量开始,都要对齐到某个对齐数的整数倍的地址处
03. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,
所有对齐数中最大的)的整数倍。
04. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍 处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

3.2.1 对⻬数

编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
VS 中默认的值为 8 Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩

3.2.2 例子

空间换时间 故而尽量让占用空间小的成员尽量集中在⼀起

3.2.3修改默认对⻬数

#pragma pack(1)//设置默认对⻬数为1
#pragma pack() //取消设置的对⻬数,还原为默认


3.3 结构体传参

参数要压栈,会有时间和空间上的系统开销。结构体过大,开销较大,性能会降低,故而传地址。

struct S { int data[1000]; int num; }; struct S s = { {1,2,3,4}, 1000 }; void print2(struct S* ps) { printf("%d\n", ps->num); } int main() { print2(&s); //传地址 return 0; }

3.4 结构体实现位段

3.4.1 位段声明+结构

  • 01. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他整型家族类型。
  • 02. 位段的成员名后边有⼀个冒号和⼀个数字
struct A { int _a : 2; int _b : 5; };

3.4.2 位段的内存分配

  • 位段的成员可以是 int unsigned int signed int 或者是 char 等类型

  • 位段的空间上是按照需要以4个字节( int )或1个字节( char )的⽅式开辟的。

  • 位段涉及很多不确定因素,位段不跨平台,注重可移植的程序应避免使⽤位段。

3.4.3 位段的跨平台问题

  • int 位段被当成有符号数还是⽆符号数是不确定的。
  • 位段中最⼤位的数⽬不能确定
  • 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
  • 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利⽤,这是不确定的。

3.4.4 位段使用注意事项

  • 位段的⼏个成员共有同⼀个字节,有成员的起始位置并不是某个字节的起始位置,没有地址。
  • 内存中每个字节分配⼀个地址,⼀个字节内部的bit位是没有地址的。
  • 不能对位段的成员使⽤&操作符,不能scanf直接给位段的成员输⼊值,只能是先输⼊放在⼀个变量中,然后赋值给位段的成员
struct A { int _a : 2; int _b : 5; int _c : 10; int _d : 30; }; int main() { struct A sa = {0}; scanf("%d", &sa._b);//这是错误的 //正确的⽰范 int b = 0; scanf("%d", &b); sa._b = b; return 0; }

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

相关文章:

  • 株洲奢侈品回收哪里靠谱?2026最新实测门店排名,按实力分级推荐 - 生活测评小能手
  • MotorViz
  • 【信息科学与工程学】【物理/化学科学和工程技术】知识体系081 磁学02
  • 分布式共识算法实战:用 Go 从零实现一个带心跳与选举的可调试 Raft 节点模型
  • JavaQuestPlayer:终极跨平台QSP游戏引擎,3分钟打造你的游戏世界
  • 3分钟解锁网易云音乐隐藏功能:BetterNCM安装工具完全指南
  • STM32H743 HAL版SD卡读写工程包:含时钟配置、DMA传输与实测hex文件
  • 2026年 净化空调生产工厂:高效节能/无尘车间/净化中央空调系统,医用级洁净技术与智慧温控有实力的供应商 - 品牌企业推荐师(官方)
  • 华硕笔记本性能控制的革命:G-Helper如何让你告别Armoury Crate的臃肿体验
  • 2026金刚石刀具供应厂家:东莞金刚石V座刀具、车刀、镗刀、铣刀及氮化硼刀具实力品牌深度解析 - 品牌企业推荐师(官方)
  • 丹阳配镜常见问题解答(2026最新专家版) - 资讯速览
  • 2026年地下水位监测设备厂家排行榜与选型指南 - 王工聊地下水监测
  • TTS芯片和语音播放芯片有什么区别?选型前必读
  • Vidupe视频去重工具:三步搞定重复视频的终极解决方案
  • STM32项目实战:IWDG与WWDG到底怎么选?CubeMX配置与HAL库代码对比解析
  • 答疑解惑|Uboot阶段访问某个地址导致系统挂死(DE25-Nano开发板)(地址对齐)
  • 便携式荧光法溶解氧仪优质厂家TOP10 - 仪表品牌排行榜
  • CSDN数字营销ROI计算总出错?根源竟是站外广告跳转被误判为站内点击——4步数据清洗法立即生效
  • 2026丹阳配镜深度测评:如何为你的配镜需求匹配最佳方案? - 资讯速览
  • 谷歌外链怎么做:手把手教你用Ahrefs直接截胡同行的优质外链
  • 2026泰安市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • pip设置镜像
  • 如何用Untrunc恢复损坏视频文件:从原理到实践的完整指南
  • 刀具磨损实时检测工具包:YOLOv11+EMSCP优化版,含界面操作、批量预测与实拍数据集
  • 杭州黄金回收实地体验对比!真实交易感受差别很大 - 奢侈品回收评测
  • 从课程作业到项目实战:如何用面向对象Python重构你的连杆机构仿真程序
  • rag的图文多模态
  • CSDN AI数据看板能否查关键词排名?实测5类API接口+4层权限验证后给出 definitive 答案
  • 不同情况怎么卖黄金?杭州各类人群黄金变现适配指南 - 奢侈品回收评测
  • 淘宝评论API接口返回参数详解