C语言 自定义类型:结构体 与 联合体

目录:

1、结构体类型的声明

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

3、结构体内存的对齐

4、结构体实现位段

一、 结构体的声明

在声明结构体的时候,可以不完全的声明

struct

{

int a;

char b;

float c;

}s;

struct

{

int a;

char b;

float c;

}* ps;

int main()

{

ps = &s;

//这种写法是有问题的,虽然上面两个匿名结构体类型成员一摸一样,

// 但是在编译器看来,是两个不同的类型

return 0;

}

二、结构体的自引用

struct Node

{

int data;

struct Node* next; // 👈 这就是自引用

};

重点:

必须用指针 struct Node,不能用 struct Node!

为什么要用自引用?(用来做链表!)

你可以把它理解成:

火车车厢

  • 每节车厢 = 一个结构体
  • 车厢里有一个 "钩子" = 指针
  • 钩子钩住下一节车厢

这就是链表 !结构体自引用 = 造链表的核心

结构体自引用 = 结构体内部包含一个指向自己的指针

作用:用来造链表、二叉树、图等复杂数据结构!

三、结构体内存对齐

结构体成员默认情况下不一定是连续存放的,由下面这段代码可以证明:

struct s1

{

char c1;

int i;

char c2;

};

struct s2

{

char c1;

char c2;

int i;

};

int main()

{

printf("%zu\n", sizeof(struct s1));

printf("%zu\n", sizeof(struct s2));

return 0;

}

为什么要对齐?

为了让 CPU读得更快 。结构体不是挨个紧挨着存的,而是按规则排队、有空位

结构体对齐规则

1. 第一个成员 从偏移 0 开始

2. 从第二个成员开始

对齐到 它自己大小 的整数倍地址

  • char (1) → 对齐到 1 的倍数
  • int (4) → 对齐到 4 的倍数
  • double (8) → 对齐到 8 的倍数

3. 结构体总大小

必须是 最大成员类型大小 的整数倍

4. 如果有嵌套结构体

嵌套的内部成员对齐到 自己最大成员的大小

四、结构体的位段

位段类型:

:冒号 后面加上 数字 (这个数字表示这个成员需要占用多少个二进制位)

当剩余空间不够时,会新开一个单元

放不下就重新开一块空间,不跨单元存放

struct A

{

int _a : 2;

int _b : 5;

int _c : 10;

int _d : 30;

}; // 当你这么设计位段成员的时候,就意味着这些成员的长度足够自己使用

位段的内存分配

为什么要用位段?

省空间!

  • 正常 int 要 4 字节(32 位)
  • 但很多数据根本用不到那么多位比如:性别(0/1)、状态(0~7)

用位段可以把多个变量挤在同一个字节里

位段的特点(超级重要)

  1. 节省内存
  2. 不能取地址 & (原因:位段的几个成员共有同一个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处是没有地址的。内存中每个字节分配一个地址,一个字节内部的bit位是没有地址的,所以不能对位段成员使用&操作符,这样就不能使用scanf直接给位段的成员输入值,只能是先输入放在一个变量中,然后赋值给位段的成员)
  3. 不能跨平台,移植性差
  4. 不能用数组
  5. 主要用于协议、硬件寄存器、网络包等对空间要求极高的地方

位段分配内存的规则

  1. 位段是按 "位" 分配,不是按字节
  2. 先从低位往高位填(从右往左填)
  3. 当前单元剩下的位不够放 → 浪费掉,新开一个单元
  4. 单元大小由 "位段的类型" 决定
    • int 型位段 → 单元 = 4 字节(32 位)
    • char 型位段 → 单元 = 1 字节(8 位)
相关推荐
Highcharts.js20 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
头发还在的女程序员1 天前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
爱写代码的小朋友1 天前
从零开始学 Win32 API:C++ 窗口编程实战(VS Code + MinGW-w64 命令行详解)
开发语言·c++
果汁华1 天前
Function Calling 与 Python 实战完整指南
开发语言·网络·python
小小晓.1 天前
C++:语句和作用域
开发语言·c++
wanderist.1 天前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
海天鹰1 天前
PHP上传文件
android·开发语言·php
稚南城才子,乌衣巷风流1 天前
动态开点:原理、实现与应用场景
数据结构·算法
yyds_yyd_100861 天前
1464. 数组中两元素的最大乘积(2026.07.27)
数据结构·c++·算法·leetcode
Yeauty1 天前
渲染成图再 CLI 拼接,还是进程内直推?Rust 帧到视频的两条路
开发语言·rust·音视频