C语言结构体深入解析【结构体嵌套结构体,结构体变量和指针,结构体和函数,计算结构体大小,结构体数组,结构体成员的访问,结构体与联合】

C语言结构体深入解析

目录

  • C语言结构体深入解析
    • 前言
    • 结构体的定义
    • 结构体在内存中的表示
    • 结构体变量初始化
      • 直接定义并初始化
      • 使用自己定义的结构体变量初始化新变量
      • 结构体数组初始化
    • 结构体中嵌套结构体
    • 结构体成员访问
      • 点操作符(`.`)
      • 箭头操作符(`->`)
    • 结构体变量和指针
      • 结构体指针定义与初始化
        • 动态分配内存
        • 比较与应用场景
    • 结构体和函数
      • 结构体作为函数参数
      • 结构体指针作为函数参数
      • 结构体作为函数返回值
      • 动态分配结构体并在函数中使用
    • 结构体与数组
      • 结构体数组
      • 结构体中嵌套数组
      • 结构体指针数组
    • 计算结构体大小
      • 计算结构体大小步骤:
        • 查看结构体大小
    • 结构体与联合
    • 结语

前言

在C语言编程的世界里,结构体(struct)是一种复合数据类型,它允许你将不同类型的数据组合在一起,形成一个单一的复杂实体。这种特性极大地丰富了C语言处理现实世界问题的能力,特别是在设计复杂的数据结构和实现面向对象编程概念时。本文旨在深入探讨C语言中的结构体,包括其定义、使用场景、内存布局、对齐规则、以及高级应用技巧。

结构体的定义

结构体通过struct关键字来定义,基本形式如下:

struct 结构体名{成员列表(基本数据类型、指针、数组或其他结构体类型)
}

例如 定义一个学生结构体
C语言结构体深入解析

结构体在内存中的表示

C语言结构体深入解析

结构体变量初始化

直接定义并初始化

C语言结构体深入解析

使用自己定义的结构体变量初始化新变量

您可以使用已定义的结构体变量来初始化同类的新结构体变量。这是通过简单的赋值操作完成的,因为结构体变量之间可以整体赋值,只要它们是同一种结构体类型。
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体数组初始化

结构体数组的初始化可以通过直接在定义结构体数组时赋予初始值来完成
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体中嵌套结构体

结构体(struct)同样支持嵌套使用,即在一个结构体中定义另一个结构体类型的成员。这种特性对于组织复杂的数据结构特别有用,可以让数据更加模块化和层次化。
案例:假设我们有两个结构体,一个表示人(Person),另一个表示地址(Address
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体成员访问

点操作符(.)

是最直接的方式,用于访问结构体变量的成员。比如定义一个表示学生的结构体,包含姓名(name)和年龄(age)两个成员:
C语言结构体深入解析
输出结果:
C语言结构体深入解析

箭头操作符(->)

访问结构体成员:当你有一个指向结构体的指针时,可以使用箭头操作符(->)来访问该结构体的成员。处理结构体数组、动态分配的结构体或通过函数传递结构体指针等场景中非常有用。下面是使用箭头操作符访问结构体成员的一个示例:
C语言结构体深入解析
输出结果
C语言结构体深入解析
在这个例子中,我们使用malloc函数动态分配了Student结构体的内存,并将返回的指针存储在studentPtr中。之后,我们使用箭头操作符(->)来访问和修改结构体成员,如studentPtr->namestudentPtr->age。这种方式与之前使用点操作符直接访问结构体成员的语法相似,但适用于结构体指针的情况。最后,别忘了在不再需要时释放通过malloc分配的内存。

结构体变量和指针

结构体是一种复合数据类型,允许你组合不同类型的多个数据项(成员)到一个单独的实体中。结构体变量直接存储结构体的所有成员,而结构体指针则存储结构体变量的地址。

结构体指针定义与初始化

以下是结构体变量和指针的一些关键点和使用方法:
C语言结构体深入解析
输出结果
C语言结构体深入解析

动态分配内存

结构体指针常用于动态地在堆上分配结构体实例的内存。
C语言结构体深入解析
输出结果:
在这里插入图片描述

比较与应用场景
  • 结构体变量适合于当结构体较小,或者结构体的生命周期与定义它的作用域相同的情况。
  • 结构体指针在处理大型结构体、动态内存分配、函数参数传递(尤其是需要修改结构体内容时)以及实现复杂数据结构(如链表、树等)时更为灵活和高效。

结构体和函数

在C语言中,结构体与函数的结合使用非常常见,主要用于封装数据和操作这些数据的函数。结构体可以作为函数的参数、返回值,也可以在函数内部定义和使用。

结构体作为函数参数

将结构体作为函数的参数,可以实现对结构体数据的操作封装,增强代码的模块化和可读性。
C语言结构体深入解析
C语言结构体深入解析

结构体指针作为函数参数

常见的作法是使用结构体指针作为函数参数,这样可以避免赋值整个结构体的开销,特别是结构体比较大时
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体作为函数返回值

虽然C语言允许结构体作为函数的返回值,但需要注意的是,如果结构体过大可能会导致栈溢出问题。小结构体或指针作为返回值比较常见。
C语言结构体深入解析
输出结果
C语言结构体深入解析

动态分配结构体并在函数中使用

对于大型结构体或需要在函数间共享数据的情况,通常会动态非陪结构体,并通过指针传递和返回。
C语言结构体深入解析
输出结果
C语言结构体深入解析

结构体与数组

c语言中,结构体和数组都是重要的数据结构,他们可以结合起来使用,以实现复杂的数据管理和操作。

结构体数组

结构体数组允许你创建一个数组,其中每个元素都是相同的结构体类型,这对于存储一系列具有相同属性的对象非常有用,比如存储一组学生的记录。
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体中嵌套数组

除了数组包含结构体外,结构体内部也可以嵌套数组,这再处理一些固定大小的数据集时很有用。
C语言结构体深入解析
输出结果:
C语言结构体深入解析

结构体指针数组

有时候,可能需要一个数组来存储指向结构体的指针,这在动态分配结构体或者需要灵活的重排数据的时候非常有用。
C语言结构体深入解析
在这里插入图片描述

计算结构体大小

在C语言中,结构体(struct)的大小由其所有成员的大小以及各成员之间的内存对齐规则共同决定。结构体的大小至少要能容纳其最大成员的大小,同时考虑到CPU访问效率,结构体成员通常会按一定的字节边界对齐。不同编译器和平台可能有不同的默认对齐规则,但通常情况下,结构体的大小会是其成员大小和对齐要求的某种整数倍。

计算结构体大小步骤:

  • 确定每个成员的大小:首先,确定结构体中每个成员的数据类型及其对应的大小(例如,int通常是4字节,char1字节等)。
  • 考虑对齐要求:根据编译器和目标平台的对齐规则,确定每个成员相对于结构体起始位置的偏移量。一般而言,成员会被放置在满足其自然对齐要求的位置上,比如int类型的自然对齐通常是4字节边界,double可能是8字节边界。
  • 计算结构体总大小:结构体的总大小是最后一个成员的末尾到结构体起始位置的距离,同时确保这个总大小满足最严格的对齐要求。如果最后一个成员后面还有未使用的空间以满足对齐,这部分也会被计入结构体的总大小。

示例:

	struct Example {char a;      // 1字节int b;       // 通常4字节char c;      // 1字节};
  • char a1字节。
  • int b需要对齐到4字节边界,因此在a之后可能会有3字节的填充(如果a之后直接跟b,则b不会在其自然边界上对齐)。
  • char c再占1字节。
    最终,尽管数据内容只需6字节(1+4+1),但由于对齐要求,结构体的实际大小可能会是8字节(具体取决于编译器的对齐策略,这里假设为了保持int b4字节对齐,在ab之间有3字节填充,加上c之后总共8字节,满足最严格的4字节对齐)。
查看结构体大小

可以使用sizeof运算符来获取特定结构体类型的大小,如:

printf("Size of struct Example: %zu\n", sizeof(struct Example));

这会直接输出该结构体类型的字节大小。

结构体与联合

结构体与联合(union)都是复合数据类型,但联合的所有成员共享同一块内存区域,而结构体的每个成员都有独立的内存空间。联合在需要节省内存且只有一项成员有效的情景下使用。

结语

结构体作为C语言中的重要组成部分,为程序设计者提供了构建复杂数据模型的强大工具。理解其内存布局、对齐规则以及如何高效利用结构体指针,对于编写高效、可维护的代码至关重要。掌握结构体的高级应用,能进一步提升解决实际问题的能力,特别是在系统编程、网络编程以及游戏开发等领域。希望本文能帮助你深化对C语言结构体的理解,并在实践中灵活运用。

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

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

相关文章

@RequestMapping属性详解及案例演示

RequestMapping源码 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented Mapping public interface RequestMapping {String name() default "";AliasFor("path")String[] value() default {};AliasFor(&quo…

智能写作与痕迹消除:AI在创意文案和论文去痕中的应用

作为一名AI爱好者,我积累了许多实用的AI生成工具。今天,我想分享一些我经常使用的工具,这些工具不仅能帮助提升工作效率,还能激发创意思维。 我们都知道,随着技术的进步,AI生成工具已经变得越来越智能&…

简单分享 for循环,从基础到高级

1. 基础篇:Hello, For Loop! 想象一下,你想给班上的每位同学发送“Hello!”,怎么办?那就是for循环啦, eg:首先有个名字的列表,for循环取出,分别打印 names ["Alice", …

bigNumber的部分使用方法与属性

场景:最近做IoT项目的时候碰到一个问题,涉及到双精度浮点型的数据范围的校验问题。业务上其实有三种类型:int、float和double类型三种。他们的范围分别是: //int int: [-2147483648, 2147483647],//float float: [-3402823466385…

PHP7源码结构

PHP7程序的执行过程 1.PHP代码经过词法分析转换为有意义的Token; 2.Token经过语法分析生成AST(Abstract Synstract Syntax Tree,抽象语法树); 3.AST生成对应的opcode,被虚拟机执行。 源码结构&#xff1…

一切为了安全丨2024中国应急(消防)品牌巡展武汉站成功召开!

消防品牌巡展武汉站 6月28日,由中国安全产业协会指导,中国安全产业协会应急创新分会、应急救援产业网联合主办,湖北消防协会协办的“一切为了安全”2024年中国应急(消防)品牌巡展-武汉站成功举办。该巡展旨在展示中国应急(消防&am…

qt QTreeView的简单使用(多级子节点)

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);setWindowTitle("QTreeView的简单使用");model new QStandardItemModel;model->setHorizontalHeaderLabels(QStringList() << "left&q…

[leetcode]longest-arithmetic-subsequence-of-given-difference. 最长定差子序列

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int longestSubsequence(vector<int> &arr, int difference) {int ans 0;unordered_map<int, int> dp;for (int v: arr) {dp[v] dp[v - difference] 1;ans max(ans, dp[v]);}return ans…

Qt源码分析:窗体绘制与响应

作为一套开源跨平台的UI代码库&#xff0c;窗体绘制与响应自然是最为基本的功能。在前面的博文中&#xff0c;已就Qt中的元对象系统(反射机制)、事件循环等基础内容进行了分析&#xff0c;并捎带阐述了窗体响应相关的内容。因此&#xff0c;本文着重分析Qt中窗体绘制相关的内容…

如何完成域名解析验证

一&#xff1a;什么是DNS解析&#xff1a; DNS解析是互联网上将人类可读的域名&#xff08;如www.example.com&#xff09;转换为计算机可识别的IP地址&#xff08;如192.0.2.1&#xff09;的过程&#xff0c;大致遵循以下步骤&#xff1a; 查询本地缓存&#xff1a;当用户尝…

顺序串算法库构建

学习贺利坚老师顺序串算法库 数据结构之自建算法库——顺序串_创建顺序串s1,创建顺序串s2-CSDN博客 本人详细解析博客 串的概念及操作_串的基本操作-CSDN博客 版本更新日志 V1.0: 在贺利坚老师算法库指导下, 结合本人详细解析博客思路基础上,进行测试, 加入异常弹出信息 v1.0补…

已解决java.awt.geom.NoninvertibleTransformException:在Java2D中无法逆转的转换的正确解决方法,亲测有效!!!

已解决java.awt.geom.NoninvertibleTransformException&#xff1a;在Java2D中无法逆转的转换的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 1. 检查缩放因子 修改后的缩放变换 …

关键路径——C语言(理论)

关键路径&#xff0c;是项目网络中从起始事件到终止事件的最长路径&#xff0c;决定了项目的最短完成时间。 关键路径中的任务没有任何可调整的余地&#xff0c;如果任何一个任务被延迟&#xff0c;整个项目的完成时间也会被延迟。 假设我们现在有一个图&#xff1a;把图的边…

【CH32V305FBP6】USBD HS 虚拟串口分析

文章目录 前言分析端点 0USBHS_UIS_TOKEN_OUT 端点 2USBHS_UIS_TOKEN_OUTUSBHS_UIS_TOKEN_IN 前言 虚拟串口&#xff0c;端口 3 单向上报&#xff0c;端口 2 双向收发。 分析 端点 0 USBHS_UIS_TOKEN_OUT 设置串口参数&#xff1a; 判断 USBHS_SetupReqCode CDC_SET_LIN…

从零开始实现大语言模型(一):概述

1. 前言 大家好&#xff0c;我是何睿智。我现在在做大语言模型相关工作&#xff0c;我用业余时间写一个专栏&#xff0c;给大家讲讲如何从零开始实现大语言模型。 从零开始实现大语言模型是了解其原理及领域大语言模型实现路径的最好方法&#xff0c;没有之一。已有研究证明&…

Windows10录屏,教你3个方法,简单快速录屏

“我的电脑系统是Windows10的系统&#xff0c;今晚要进行线上开会&#xff0c;但我实在有事没办法参加会议&#xff0c;想把会议的内容录制下来方便我后续观看。但却找不到电脑录屏功能在哪里打开&#xff1f;求助一下&#xff0c;谁能帮帮我&#xff1f;” 在数字化时代&…

mysql 命令 —— 查看表信息(show table status)

查询表信息&#xff0c;如整个表的数据量大小、表的索引占用空间大小等 1、查询某个库下面的所有表信息&#xff1a; SHOW TABLE STATUS FROM your_database_name;2、查询指定的表信息&#xff1a; SHOW TABLE STATUS LIKE your_table_name;如&#xff1a;Data_length 显示表…

闲聊 .NET Standard

前言 有时候&#xff0c;我们从 Nuget 下载第三方包时&#xff0c;会看到这些包的依赖除了要求 .NET FrameWork、.NET Core 等的版本之外&#xff0c;还会要求 .NET Standard 的版本&#xff0c;比如这样&#xff1a; 这个神秘的 .NET Standard 是什么呢&#xff1f; .NET St…

从零开始搭建spring boot多模块项目

一、搭建父级模块 1、打开idea,选择file–new–project 2、选择Spring Initializr,选择相关java版本,点击“Next” 3、填写父级模块信息 选择/填写group、artifact、type、language、packaging(后面需要修改)、java version(后面需要修改成和第2步中版本一致)。点击“…

工业触摸一体机优化MES应用开发流程

工业触摸一体机在现代工业生产中扮演着至关重要的角色&#xff0c;它集成了智能触摸屏和工业计算机的功能&#xff0c;广泛应用于各种生产场景中。而制造执行系统&#xff08;MES&#xff09;作为工业生产管理的重要工具&#xff0c;对于提高生产效率、降低成本、优化资源利用具…