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

【重新认识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-------------------------------------

相关文章:

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

目录 -----------------------------------------begin------------------------------------- 引言 1. 结构体的基本概念 1.1 为什么需要结构体&#xff1f; 1.2 结构体的定义 2. 结构体变量的声明与初始化 2.1 声明结构体变量 2.2 初始化结构体变量 3. 结构体成员的访…...

#渗透测试#批量漏洞挖掘#Splunk Enterprise for Windows 任意文件读取漏洞( CVE-2024-36991)

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

苹果公司宣布正式开源 Xcode 引擎 Swift Build145

2025 年 2 月 1 日&#xff0c;苹果公司宣布正式开源 Xcode 引擎 Swift Build145。 Swift 是苹果公司于 2014 年推出的一种开源编程语言&#xff0c;用于开发 iOS、iPadOS、macOS、watchOS 和 tvOS 等平台的应用程序。 发展历程 诞生&#xff1a;2014 年&#xff0c;苹果在全球…...

7.list

本篇博客梳理C的STL中的list容器 一、list的基本结构与使用 1&#xff0e;list的介绍 list的底层是带头循环双向链表 带头&#xff1a;含哨兵位 循环&#xff1a;尾节点的next指针指向哨兵位 双向&#xff1a;每个节点具有两个指针域&#xff0c;一个指针指向前一个结点 2…...

Qt+海康虚拟相机的调试

做机器视觉项目的时候&#xff0c;在没有相机或需要把现场采集的图片在本地跑一下做测试时&#xff0c;可以使用海康的虚拟相机调试。以下是设置步骤&#xff1a; 1.安装好海康MVS软件&#xff0c;在菜单栏->工具选择虚拟相机工具&#xff0c;如下图&#xff1a; 2.打开虚拟…...

数据库基础练习4(有关索引,视图完整解答)

建立需要的表 学生表 mysql> create table studnet(sno int primary key auto_increment,sname varchar(30) not null unique,ssex varchar(2) check (ssex男 or ssex女) not null ,sage int not null,sdept varchar(10) default 计算机 not null); Query OK, 0 rows affe…...

实操给触摸一体机接入大模型语音交互

本文以CSK6 大模型开发板串口触摸屏为例&#xff0c;实操讲解触摸一体机怎样快速增加大模型语音交互功能&#xff0c;使用户能够通过语音在一体机上查询信息、获取智能回答及实现更多互动功能等。 在本文方案中通过CSK6大模型语音开发板采集用户语音&#xff0c;将语音数据传输…...

Excel中对单列数据进行去重筛选

在Excel中对单列数据进行去重筛选&#xff0c;可以按照以下步骤操作&#xff1a; 方法一&#xff1a;使用“删除重复项”功能 选择数据列&#xff1a;点击要处理的列头&#xff08;如A列&#xff09;。打开“删除重复项”&#xff1a; Excel 2007及以后版本&#xff1a;点击“…...

K8s —基础指南(K8s - Basic Guide)

K8s —基础指南 K8s 是云上部署容器化应用的事实标准。它作为容器的强大编排器&#xff0c;管理容器重启、负载均衡等任务。 理解 Kubernetes 架构 Kubernetes 的关键功能之一是为访问 Pod 提供稳定的端点&#xff0c;尽管 Pod 本身是短暂的。Kubernetes 服务有效地弥补了这…...

ABAP开发中的前导零和末尾零

前导零和末尾零是指分别出现在数字序列中第一个非零数字之前和最后一个非零数字之后的任何零数字。 关于前导 0 在 SAP 系统中&#xff0c;大多数字母数字字段在数据库中存储时都带前导零&#xff0c;完全占用字段的定义长度。但是&#xff0c;当字段显示给最终用户时&#x…...

Baklib赋能数字内容体验个性化推荐提升用户体验的未来之路

内容概要 随着数字化时代的不断发展&#xff0c;用户对内容消费的需求日益多样化&#xff0c;个性化推荐成为提升用户体验的重要手段。Baklib以其先进的技术手段&#xff0c;在数字内容领域内积极推动个性化推荐的实施&#xff0c;从而满足用户在信息获取和内容消费中的独特需…...

关于Redis的持久化

目录 RDB 1.手动触发 2.自动触发 AOF aof的重写机制 Redis虽然是一个内存数据库&#xff0c;但是也是可以将数据存储到硬盘中的&#xff0c;也就是持久化。硬盘的数据是在Redis重启的时候&#xff0c;用来恢复内存中的数据的&#xff0c;即对数据做了一个备份。Redis实现持…...

【C语言标准库函数】指数与对数函数:exp(), log(), log10()

目录 一、头文件 二、函数简介 2.1. exp(double x) 2.2. log(double x) 2.3. log10(double x) 三、函数实现&#xff08;概念性&#xff09; 3.1. exp(double x) 的模拟实现 3.2. log(double x) 和 log10(double x) 的模拟实现 四、注意事项 4.1. exp(double x) 的注…...

2024美团春招硬件开发笔试真题及答案解析

目录 一、选择题 1、在 Linux,有一个名为 file 的文件,内容如下所示: 2、在 Linux 中,关于虚拟内存相关的说法正确的是() 3、AT89S52单片机中,在外部中断响应的期间,中断请求标志位查询占用了()。 4、下列关于8051单片机的结构与功能,说法不正确的是()? 5、…...

Python内置函数map(), list(), len(), iter(), hex(), hash()的详细解析,包括功能、语法、示例及注意事项

1. map(function, iterable, ...) 功能&#xff1a;对可迭代对象中的每个元素应用指定函数&#xff0c;返回一个迭代器。 参数&#xff1a; function&#xff1a;要执行的函数&#xff08;可以是lambda表达式&#xff09;。 iterable&#xff1a;一个或多个可迭代对象&#x…...

[LVGL] 在VC_MFC中移植LVGL

前言&#xff1a; 0. 在MFC中开发LVGL的优点是可以用多个Window界面做辅助扩展【类似GUIguider】 1.本文基于VC2022-MFC单文档框架移植lvgl8 2. gitee上下载lvgl8.3 源码&#xff0c;并将其文件夹改名为lvgl lvgl: LVGL 是一个开源图形库&#xff0c;提供您创建具有易于使用…...

MySQL视图索引操作

创建学生表&#xff1b; mysql> create table Student(-> Sno int primary key auto_increment,-> Sname varchar(30) not null unique,-> Ssex char(2) check (Ssex男 or Ssex女) not null,-> Sage int not null,-> Sdept varchar(10) default 计算机 not …...

一次奇怪的空指针问题分析:事务、死锁与隐式回滚

最近我们在排查一个诡异的 空指针异常&#xff0c;整个分析过程可以说是跌宕起伏&#xff0c;最终的结论也颇具隐蔽性。今天就把这个问题分享出来&#xff0c;希望对大家有所帮助。 问题现象 在系统中&#xff0c;我们有 单据 B&#xff0c;它通过一个 关联 ID 字段与 上级单…...

解决aspose将Excel转成PDF中文变成方框的乱码问题

原文网址&#xff1a;解决aspose将Excel转成PDF中文变成方框的乱码问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何解决aspose将Excel转成PDF中文变成方框的乱码问题。 问题描述 用aspose将word、excel等转成PDF后&#xff0c;英文展示正常&#xff0c;但中文全部变成了…...

.net8.0使用EF连接sqlite数据库及使用Gridify实现查询的简易实现

EF Core EF Core 是一个流行的对象关系映射&#xff08;ORM&#xff09;框架&#xff0c;它简化了与数据库的交互&#xff0c;提供了一个高效、灵活且易于使用的数据访问层。 Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...