【重新认识C语言----结构体篇】

目录

-----------------------------------------begin-------------------------------------

引言

1. 结构体的基本概念

1.1 为什么需要结构体?

1.2 结构体的定义

2. 结构体变量的声明与初始化

2.1 声明结构体变量

2.2 初始化结构体变量

3. 结构体成员的访问

3.1 使用点运算符(.)

3.2 结构体指针与箭头运算符(->)

4. 结构体的内存布局

4.1 内存对齐规则

4.2 手动控制内存对齐

5. 结构体的高级用法

5.1 结构体数组

5.2 嵌套结构体

5.3 结构体与函数

5.4 使用typedef简化结构体类型名

6. 结构体与联合体(Union)的区别

7. 综合示例:学生管理系统

8. 常见问题与注意事项

结语

路过的佬们点点关注哦~

你们的鼓励是我前进的动力~

-------------------------------------------end-------------------------------------


-----------------------------------------begin-------------------------------------

引言

在C语言编程中,结构体(Structure) 是一种非常重要的复合数据类型。它允许开发者将多个不同类型的变量组合成一个逻辑单元,从而更高效地管理复杂数据。无论是实现链表、树等数据结构,还是描述现实世界中的实体(如学生、商品等),结构体都扮演着核心角色。本文将详细讲解结构体的定义、使用及高级特性,帮助读者彻底掌握这一关键概念。


1. 结构体的基本概念

1.1 为什么需要结构体?

假设我们需要描述一个学生的信息,包括姓名(字符串)、学号(整数)、年龄(整数)和成绩(浮点数)。如果单独使用多个变量来存储这些信息,代码会变得冗长且难以维护。例如:

char name[20];
int id;
int age;
float score;

结构体可以将这些变量封装为一个整体,使数据管理更加清晰。

1.2 结构体的定义

结构体通过 struct 关键字定义,语法如下:

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

示例:定义一个学生结构体

struct Student {char name[20];int id;int age;float score;
};

2. 结构体变量的声明与初始化

2.1 声明结构体变量

结构体定义后,可以通过两种方式声明变量:

  1. 在定义结构体时直接声明变量

    struct Student {// 成员定义
    } stu1, stu2;  // 直接声明变量stu1和stu2

  2. 通过结构体类型名声明变量

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

    2.2 初始化结构体变量

    结构体变量可以在声明时初始化,或通过赋值操作初始化。
    示例:

// 声明时初始化
struct Student stu1 = {"Alice", 1001, 18, 90.5};// 单独赋值初始化
struct Student stu2;
strcpy(stu2.name, "Bob");
stu2.id = 1002;
stu2.age = 19;
stu2.score = 85.0;

3. 结构体成员的访问

3.1 使用点运算符(.

通过 . 运算符可以直接访问结构体变量的成员:

printf("学生姓名:%s\n", stu1.name);
printf("学号:%d\n", stu1.id);

3.2 结构体指针与箭头运算符(->

如果通过指针访问结构体成员,需使用 -> 运算符:

struct Student *pStu = &stu1;
printf("年龄:%d\n", pStu->age);  // 等价于 (*pStu).age

4. 结构体的内存布局

4.1 内存对齐规则

为了提高内存访问效率,结构体的成员在内存中遵循对齐规则:

  • 对齐数(Alignment):成员的大小与编译器默认对齐数中的较小值。

  • 起始地址:每个成员的起始地址必须是对齐数的整数倍。

  • 总大小:结构体的总大小是对齐数最大值的整数倍。

示例:

struct Example {char c;     // 1字节,对齐数为1int i;      // 4字节,对齐数为4double d;   // 8字节,对齐数为8
};

内存布局分析:

  • char c 占1字节,起始地址0。

  • int i 对齐数为4,起始地址需是4的倍数,因此填充3字节(地址1~3),起始地址4。

  • double d 对齐数为8,起始地址8。
    总大小 = 1 + 3(填充) + 4 + 8 = 16字节。

4.2 手动控制内存对齐

通过 #pragma pack(n) 可以修改默认对齐数(n为1、2、4、8等):

#pragma pack(1)  // 设置为1字节对齐
struct PackedExample {char c;int i;double d;
};
#pragma pack()   // 恢复默认对齐

此时结构体总大小为 1 + 4 + 8 = 13字节。

5. 结构体的高级用法

5.1 结构体数组

结构体数组用于存储多个相同类型的结构体变量。
示例:

struct Student students[3] = {{"Alice", 1001, 18, 90.5},{"Bob", 1002, 19, 85.0},{"Charlie", 1003, 20, 92.0}
};

5.2 嵌套结构体

结构体可以嵌套其他结构体作为成员。
示例:

struct Date {int year;int month;int day;
};struct Employee {char name[20];struct Date birthday;
};

5.3 结构体与函数

结构体可以作为函数参数或返回值传递。
示例:

// 函数参数:按值传递
void printStudent(struct Student stu) {printf("姓名:%s\n", stu.name);
}// 函数参数:按指针传递(推荐,避免内存拷贝)
void updateScore(struct Student *pStu, float newScore) {pStu->score = newScore;
}// 函数返回结构体
struct Student createStudent() {struct Student stu = {"David", 1004, 21, 88.5};return stu;
}

5.4 使用typedef简化结构体类型名

通过 typedef 可以为结构体定义别名,简化代码:

typedef struct Student {// 成员定义
} Student;  // 别名// 声明变量
Student stu4;

6. 结构体与联合体(Union)的区别

结构体与联合体(union)的区别在于内存分配方式:

  • 结构体:每个成员拥有独立的内存空间,总大小为所有成员大小之和(考虑对齐)。

  • 联合体:所有成员共享同一块内存空间,总大小等于最大成员的大小。

7. 综合示例:学生管理系统

#include <stdio.h>
#include <string.h>typedef struct Student {char name[20];int id;float score;
} Student;void printStudent(const Student *stu) {printf("姓名:%s\t学号:%d\t成绩:%.1f\n", stu->name, stu->id, stu->score);
}int main() {Student students[3];// 输入学生信息for (int i = 0; i < 3; i++) {printf("输入第%d个学生的姓名、学号和成绩:", i+1);scanf("%s %d %f", students[i].name, &students[i].id, &students[i].score);}// 输出学生信息printf("\n学生列表:\n");for (int i = 0; i < 3; i++) {printStudent(&students[i]);}return 0;
}

8. 常见问题与注意事项

  • 结构体赋值

    结构体变量可以直接赋值给同类型的变量(按值拷贝):

Student stu1 = {"Alice", 1001, 90.5};
Student stu2 = stu1;  // 合法,内存拷贝
  • 结构体大小计算

    使用 sizeof 运算符获取结构体大小,但需注意内存对齐的影响。

  • 结构体与动态内存分配

    结构体指针可以结合 malloc 实现动态内存分配:

Student *pStu = (Student*)malloc(sizeof(Student));
free(pStu);

结语

结构体是C语言中组织复杂数据的核心工具,其灵活性和高效性使其在系统编程、嵌入式开发等领域广泛应用。通过本文的学习,读者应能够熟练定义、操作结构体,并理解其底层内存布局。建议结合实际项目练习,进一步巩固这一重要概念。

路过的佬们点点关注哦~
你们的鼓励是我前进的动力~

-------------------------------------------end-------------------------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/68224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Vscode中接入Deepseek

一、获取Deepseek APIKEY 首先&#xff0c;登录Deepseek官网的开放平台&#xff1a;DeepSeek 选择API开放平台&#xff0c;然后登录Deepseek后台。 点击左侧菜单栏“API keys”&#xff0c;并创建API key。 需要注意的是&#xff0c;生成API key复制保存到本地&#xff0c;丢失…

电脑开机提示按f1原因分析及终极解决方法来了

经常有网友问到一个问题&#xff0c;我电脑开机后提示按f1怎么解决&#xff1f;不管理是台式电脑&#xff0c;还是笔记本&#xff0c;都有可能会遇到开机需要按F1&#xff0c;才能进入系统的问题&#xff0c;引起这个问题的原因比较多&#xff0c;今天小编在这里给大家列举了比…

AI协助探索AI新构型自动化创新的技术实现

一、AI自进化架构的核心范式 1. 元代码生成与模块化重构 - 代码级自编程&#xff1a;基于神经架构搜索的强化学习框架&#xff0c;AI可通过生成元代码模板&#xff08;框架的抽象层定义、神经元结点-网络拓扑态的编码抽象定义&#xff09;自动组合功能模块。例如&#xff0…

RAID独立硬盘冗余阵列

目录 一、RAID基本功能 二、RAID常见级别 三、实现方式 1、软件磁盘阵列 2、硬件磁盘阵列 四、热备盘 RAID&#xff08;Redundant Array of Independent Disks&#xff09;是一种通过将多个硬盘组合成一个逻辑单元来提升存储性能、冗余性或两者兼具的技术。 一、RAID基本…

【高级篇 / IPv6】(7.2) ❀ 04. 在60E上配置ADSL拨号宽带上网(IPv4) ❀ FortiGate 防火墙

【简介】除了单位用户以外&#xff0c;大部分个人用户目前使用的仍然是30E、50E、60E系列防火墙&#xff0c;固件无法达到目前最高版本7.6&#xff0c;这里以最常用的60E为例&#xff0c;演示固件版本7.2下实现ADSL拨号宽带的IPv6上网。由于内容比较多&#xff0c;文章分上、下…

Qt之设置QToolBar上的按钮样式

通常给QAction设置icon后,菜单栏的菜单项和工具栏(QToolBar)上对应的按钮会同时显示该icon。工具栏还可以使用setToolButtonStyle函数设置按钮样式,其参数为枚举值: enum ToolButtonStyle {ToolButtonIconOnly,ToolButtonTextOnly,ToolButtonTextBesideIcon,ToolButtonTe…

【从零开始系列】DeepSeek-R1:(本地部署使用)思维链推理大模型,开源的神!——Windows/Linux本地环境测试 + vLLM远程部署服务

目录 一、环境配置 1.硬件设备评估 2.基础环境安装 3.模型参数下载 (1) huggingface镜像源下载 (2) modelscope魔搭社区下载 &#xff08;推荐&#xff09; 二、基础使用&#xff08;Linux、Window兼容&#xff09; 1.Transformers库自编代码 三、进阶使用&#xff08;仅Lin…

DeepSeek 开源模型全解析(2024.1.1–2025.2.6)

目录 一、通用大语言模型&#xff1a;DeepSeek-V3 系列 137 二、推理优化模型&#xff1a;DeepSeek-R1 系列 811 三、多模态模型&#xff1a;Janus 系列 10 四、生态整合与部署建议 五、总结与展望 以下为 DeepSeek 在 2024 年 1 月至 2025 年 2 月期间发布的开源模型及其…

Mac: docker安装以后报错Command not found: docker

文章目录 前言解决办法&#xff08;新的&#xff09;解决步骤&#xff08;原来的&#xff09;不推荐总结 前言 ​本操作参考 http://blog.csdn.net/enhenglhm/article/details/137955756 原作者&#xff0c;更详细请&#xff0c;查看详细内容请关注原作者。 一般&#xff0c;…

《手札·开源篇》数字化转型助力永磁电机企业降本增效:快速设计软件如何让研发效率提升40%?

数字化转型助力永磁电机企业降本增效&#xff1a;快速设计软件如何让研发效率提升40%&#xff1f; 一、痛点&#xff1a;传统研发模式正在吃掉企业的利润 永磁电机行业面临两大挑战&#xff1a; 研发周期长&#xff1a;一款新电机从设计到量产需6-12个月&#xff0c;电磁计算…

0207作业

思维导图 服务器 enum Type{TYPE_REGIST,TYPE_LOGIN };typedef struct Pack{int size;enum Type type;char buf[2048];}pack_t;typedef struct list{union Data{struct List* tail;char str[64];}data;struct List* next;struct List* prev; }List;List* create_node(){List* …

深入浅出 DeepSeek V2 高效的MoE语言模型

今天&#xff0c;我们来聊聊 DeepSeek V2 高效的 MoE 语言模型&#xff0c;带大家一起深入理解这篇论文的精髓&#xff0c;同时&#xff0c;告诉大家如何将这些概念应用到实际中。 &#x1f31f; 什么是 MoE&#xff1f;——Mixture of Experts&#xff08;专家混合模型&#x…

RabbitMQ 从入门到精通:从工作模式到集群部署实战(五)

#作者&#xff1a;闫乾苓 系列前几篇&#xff1a; 《RabbitMQ 从入门到精通&#xff1a;从工作模式到集群部署实战&#xff08;一&#xff09;》&#xff1a;link 《RabbitMQ 从入门到精通&#xff1a;从工作模式到集群部署实战&#xff08;二&#xff09;》&#xff1a; lin…

nodejs:express + js-mdict 网页查询英汉词典,能播放.spx 声音

向 DeepSeek R1 提问&#xff1a; 我想写一个Web 前端网页&#xff0c;后台用 nodejs js-mdict , 实现在线查询英语单词&#xff0c;并能播放.spx 声音文件 1. 项目结构 首先&#xff0c;创建一个项目目录&#xff0c;结构如下&#xff1a; mydict-app/ ├── public/ │ …

Linux ftrace 内核跟踪入门

文章目录 ftrace介绍开启ftraceftrace使用ftrace跟踪指定内核函数ftrace跟踪指定pid ftrace原理ftrace与stracetrace-cmd 工具KernelShark参考 ftrace介绍 Ftrace is an internal tracer designed to help out developers and designers of systems to find what is going on i…

【抽象代数】1.1. 运算及关系

集合与映射 定义1. 设 为 的子集&#xff0c;定义 到 的映射 &#xff1a; 使得 &#xff0c;称 为 到 的嵌入映射。 定义2. 设 为 的子集&#xff0c; 为 到 的映射&#xff0c; 为 到 的映射&#xff0c;如果 &#xff0c;称为的开拓&#xff0c; 为 的限制&…

pytest+request+yaml+allure 接口自动化测试全解析[手动写的跟AI的对比]

我手动写的:Python3:pytest+request+yaml+allure接口自动化测试_request+pytest+yaml-CSDN博客 AI写的:pytest+request+yaml+allure 接口自动化测试全解析 在当今的软件开发流程中,接口自动化测试扮演着至关重要的角色。它不仅能够提高测试效率,确保接口的稳定性和正确性…

数据库高安全—审计追踪:传统审计统一审计

书接上文数据库高安全—角色权限&#xff1a;权限管理&权限检查&#xff0c;从权限管理和权限检查方面解读了高斯数据库的角色权限&#xff0c;本篇将从传统审计和统一审计两方面对高斯数据库的审计追踪技术进行解读。 4 审计追踪 4.1 传统审计 审计内容的记录方式通…

第三个Qt开发实例:利用之前已经开发好的LED驱动在Qt生成的界面中控制LED2的亮和灭

前言 上一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145459006 中&#xff0c;我们是直接利用GPIO子系统控制了LED2的亮和灭&#xff0c;这篇博文中我们利用之前写好的LED驱动程序在Qt的生成的界面中控制LED2的亮和灭。 之前已经在下面两篇博文中实现了LED驱动…

deepseek来讲lua

Lua 是一种轻量级、高效、可嵌入的脚本语言&#xff0c;广泛应用于游戏开发、嵌入式系统、Web 服务器等领域。以下是 Lua 的主要特点和一些基本概念&#xff1a; 1. 特点 轻量级&#xff1a;Lua 的核心非常小&#xff0c;适合嵌入到其他应用程序中。高效&#xff1a;Lua 的执…