网站首页
手机版

C++大白话系列C语言核心篇19结构体详解:自定义数据类型

更新时间:作者:小小条

结构体详解:自定义数据类型

把数据打包在一起,为链表做准备

链表好难?先搞懂结构体!

学*链表的困扰

症状:

指针好懵逼链表要炸了看不懂代码

原因: 没搞懂结构体!

C++大白话系列C语言核心篇19结构体详解:自定义数据类型

结论: 先理解结构体,链表就不难了!


问题引入

需求

从控制台输入10个学生的信息:

姓名年龄性别

如何保存?


传统做法:分散存储

使用数组

#include <stdio.h>int main() {char names[10][20]; // 10个学生的姓名int ages[10]; // 10个学生的年龄char genders[10]; // 10个学生的性别 // 输入for (int i = 0; i < 10; i++) {printf("请输入第%d个学生的信息:\n", i + 1);printf("姓名:");scanf("%s", names[i]);printf("年龄:");scanf("%d", &ages[i]);printf("性别(M/F):");scanf(" %c", &genders[i]); }return 0;}

⚠️ 问题

缺点:

数据分散关联性弱操作繁琐扩展困难

更好的做法:结构体

结构体概念

结构体 = 把不同类型的数据组合在一起

就像一个盒子,装各种东西!

基本语法

struct 结构体名 { 数据类型1 成员名1; 数据类型2 成员名2; 数据类型3 成员名3; ...};

注意末尾的分号!


定义学生结构体

示例

struct Student {char name[20]; // 姓名int age; // 年龄char gender; // 性别};

含义:

定义了一个名为 Student 的结构体类型包含三个成员:name、age、gender

声明变量

struct Student s1; // 声明一个Student类型的变量

注意: 每次都要写 struct 关键字


typedef:简化声明

问题

每次声明都要写 struct:

struct Student s1;struct Student s2;struct Student s3;

太麻烦了!

解决方案

使用 typedef 重定义类型名:

typedef struct {char name[20];int age;char gender;} Student;

现在可以这样声明:

Student s1; // 不用写 struct 了!Student s2;Student s3;

匿名结构体

typedef + 匿名结构体:

结构体本身没有名字直接定义别名 Student使用更简洁

结构体在内存中

基本布局

typedef struct {char name[20]; // 20字节int age; // 4字节char gender; // 1字节} Student;Student s1;

内存分配:

┌──────────────────────┬─────────┬────┐│ name[20] │ age │gen ││ 20字节 │ 4字节 │1字节│└──────────────────────┴─────────┴────┘

总共应该是: 20 + 4 + 1 = 25字节

但实际是: 28字节!❓


内存对齐

对齐规则

规则1:成员起始位置对齐

1字节类型:任意地址2字节类型:2的整数倍地址4字节类型:4的整数倍地址8字节类型:8的整数倍地址

规则2:结构体大小对齐

结构体总大小必须是最大成员类型的整数倍

实际布局

typedef struct {char name[20]; // 20字节int age; // 4字节char gender; // 1字节} Student;

内存分配:

地址: 0 20 24 25 ┌──────┬────┬─┬───┐ │name │age │g│填充│ │20字节│4字节│1│3字节│ └──────┴────┴─┴───┘ 20 4 1 3总计:28字节(4的整数倍)

为什么是28字节?

name:20字节(0-19地址)age:4字节(20-23地址,4字节对齐)gender:1字节(24地址)填充:3字节(25-27地址)总大小:28字节(最大成员int是4字节,28是4的倍数)

内存对齐的意义

为什么要对齐?

1. CPU访问效率

CPU一次读取4字节或8字节对齐后一次就能读取完整数据未对齐可能需要多次读取

2. 硬件要求

某些硬件要求数据对齐未对齐会导致错误

⚠️ 内存浪费

不同顺序,不同大小:

方案1:

typedef struct {char name[20]; // 20字节int age; // 4字节char gender; // 1字节} Student; // 28字节

方案2:

typedef struct {char name[20]; // 20字节char gender; // 1字节int age; // 4字节} Student; // 28字节

方案3(优化):

typedef struct {int age; // 4字节char name[20]; // 20字节char gender; // 1字节} Student; // 28字节

优化技巧

把最大类型放前面:

确定最大类型(如int = 4字节)按最大宽度排列成员尽量紧凑排列

示例:

typedef struct {double value; // 8字节int count; // 4字节char flag; // 1字节} Data; // 16字节(8的倍数)


强制1字节对齐

#pragma pack

#pragma pack(1) // 强制1字节对齐typedef struct {char name[20];int age;char gender;} Student; // 25字节#pragma pack() // 恢复默认对齐

⚠️ 不推荐

原因:

访问速度变慢CPU效率降低某些平台不支持

只在特殊场合使用:

网络协议文件格式硬件接口

结构体操作

点运算符(.)

访问结构体成员:

typedef struct {char name[20];int age;char gender;} Student;int main() {Student s1; // 赋值strcpy(s1.name, "张三");s1.age = 18;s1.gender = 'M'; // 访问printf("姓名:%s\n", s1.name);printf("年龄:%d\n", s1.age);printf("性别:%c\n", s1.gender);return 0;}

箭头运算符(->)

通过指针访问:

int main() {Student s1;Student *p = &s1; // 方式1:通过指针和点运算符 (*p).age = 18; // 方式2:通过箭头运算符(推荐)p->age = 18;p->gender = 'M';strcpy(p->name, "张三");printf("%s, %d岁, %c\n", p->name, p->age, p->gender);return 0;}

等价关系:

p->age ≡ (*p).age


完整示例:学生信息管理

代码

#include <stdio.h>#include <string.h>typedef struct {char name[20];int age;char gender;} Student;int main() {Student students[10]; // 10个学生的数组int n;printf("请输入学生人数(1-10):");scanf("%d", &n); // 输入for (int i = 0; i < n; i++) {printf("\n第%d个学生:\n", i + 1);printf("姓名:");scanf("%s", students[i].name);printf("年龄:");scanf("%d", &students[i].age);printf("性别(M/F):");scanf(" %c", &students[i].gender); } // 输出printf("\n学生信息列表:\n");printf("================================\n");printf("%-10s %-5s %-5s\n", "姓名", "年龄", "性别");printf("--------------------------------\n");for (int i = 0; i < n; i++) {printf("%-10s %-5d %-5c\n",students[i].name,students[i].age,students[i].gender); }return 0;}


结构体嵌套

结构体中包含结构体

typedef struct {int year;int month;int day;} Date;typedef struct {char name[20];int age;char gender;Date birthday; // 嵌套结构体} Student;int main() {Student s1;strcpy(s1.name, "张三");s1.age = 18;s1.gender = 'M';s1.birthday.year = 2007;s1.birthday.month = 5;s1.birthday.day = 15;printf("%s, %d岁, 生日:%d-%02d-%02d\n",s1.name, s1.age,s1.birthday.year,s1.birthday.month,s1.birthday.day);return 0;}


结构体自引用

指向自身类型的指针

typedef struct Student {char name[20];int age;struct Student *next; // 指向下一个学生} Student;

这就是链表的基础!

简单链表示例

int main() {Student s1 = {"张三", 18, NULL};Student s2 = {"李四", 19, NULL};Student s3 = {"王五", 20, NULL}; // 连接s1.next = &s2;s2.next = &s3; // 遍历Student *p = &s1;while (p != NULL) {printf("%s, %d岁\n", p->name, p->age);p = p->next; }return 0;}

输出:

张三, 18岁李四, 19岁王五, 20岁


本文要点回顾

✨ 结构体:组合不同类型数据✨ 声明:struct 或 typedef✨ 内存对齐:提高访问效率✨ 点运算符:s.member✨ 箭头运算符:p->member✨ 结构体数组:批量管理数据✨ 结构体嵌套:复杂数据结构✨ 自引用:链表的基础

记忆口诀

结构体好比一个盒,各种数据装一起。

typedef简化声明,点和箭头访问它。

内存对齐要记牢,最大类型作倍数。

自引用指针妙,链表基础就是它。


实战练*

练*1:图书信息

任务: 定义图书结构体,包含书名、作者、价格、ISBN

点击查看答案

#include <stdio.h>#include <string.h>typedef struct {char title[50];char author[30];double price;char isbn[20];} Book;int main() {Book book1;strcpy(book1.title, "C语言程序设计");strcpy(book1.author, "谭浩强");book1.price = 39.80;strcpy(book1.isbn, "978-7-302-12345-6");printf("书名:%s\n", book1.title);printf("作者:%s\n", book1.author);printf("价格:%.2f元\n", book1.price);printf("ISBN:%s\n", book1.isbn);return 0;}

练*2:计算结构体大小

任务: 预测以下结构体的大小

点击查看答案

#include <stdio.h>typedef struct {char a; // 1字节int b; // 4字节char c; // 1字节} Test1; // 12字节(4的倍数)typedef struct {char a; // 1字节char c; // 1字节int b; // 4字节} Test2; // 8字节(4的倍数)typedef struct {double a; // 8字节int b; // 4字节char c; // 1字节} Test3; // 16字节(8的倍数)int main() {printf("Test1: %d字节\n", sizeof(Test1));printf("Test2: %d字节\n", sizeof(Test2));printf("Test3: %d字节\n", sizeof(Test3));return 0;}

输出:

Test1: 12字节Test2: 8字节Test3: 16字节

练*3:链表预演

任务: 创建3个学生,用指针连接,遍历输出

点击查看答案

#include <stdio.h>#include <string.h>typedef struct Student {char name[20];int age;struct Student *next;} Student;int main() { // 创建学生Student s1, s2, s3;strcpy(s1.name, "张三");s1.age = 18;strcpy(s2.name, "李四");s2.age = 19;strcpy(s3.name, "王五");s3.age = 20; // 连接成链表s1.next = &s2;s2.next = &s3;s3.next = NULL; // 遍历Student *p = &s1;while (p != NULL) {printf("%s, %d岁\n", p->name, p->age);p = p->next; }return 0;}


互动时间

思考题:

为什么要内存对齐?能否完全避免?如何优化结构体减少内存浪费?结构体和数组有什么区别?

如果本文对你有帮助,欢迎:

点赞支持 关注不迷路 评论区分享你对结构体的理解⭐ 收藏慢慢看

—-本文为”C++ 大白话”系列第 19 篇

版权声明:本文转载于今日头条,版权归作者所有,如果侵权,请联系本站编辑删除

为您推荐

到了高中你会发现初中多重要中考成绩数学分

那两句话——“起跑线在初中”“中考决定了七八成”——我听过无数遍,从校长嘴里、家长微信群里、甚至教育局的通报里。可真正让我改变看法的,不是口头禅,而是那些档案、成绩曲

2026-01-01 09:37

2020年合肥市高中学业水平考试补考工作启动

  中安在线、中安新闻客户端讯 近日,合肥市教育考试院在合肥二中召开了全市2020年普通高中学业水平考试秋季工作会,部署2018级普通高中学生学业水平考试基础信息校对工作和2

2026-01-01 09:37

别再吼学生!5个纪律妙招,让班级瞬间安静,老师再也不头疼

开学季实操老师不再大喊课堂如何自己安静下来你有没有遇到过这样的场景:老师嗓子都喊哑了,教室却闹得像早市数据显示,最近一次校内问卷里有接近四成学生承认课堂上会分心——这

2026-01-01 09:36

阜阳史先荣:教育圈资深园丁的“主动投案”之谜

一位从教数十年的老教育工作者,在权力与责任的平衡木上最终失足各位“公门见闻录”的读者朋友们,老门主今天又得来聊一桩教育圈的新鲜事。就在昨天,阜阳二中原校长史先荣主动投

2026-01-01 09:36

2025中考语文写作专项素材积累:逆风翻盘,灿烂绽放

2025中考语文写作专项素材积累:逆风翻盘,灿烂绽放人物素材(基本信息、成长经历、成就、精神品质、经典语录、话题应用、行文构思)典型人物:海伦·凯勒(失明作家)、史铁生(轮椅哲思)、

2026-01-01 09:35

高中语文议论文写作140个人物素材(1)

⒈屈原他,长剑佩腰,纵横中原,问天索地,踌躇满志;他,朝搴木兰,夕揽宿莽,奔波效劳,鞠躬尽瘁。然而,子兰谄言,郑袖惑内,艾萧太盛,椒兰甚少,骐骥不跃,美政弗行,举世皆醉,万民同苦。勇气与理想尽灭

2026-01-01 09:35