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,一经查实,立即删除!

相关文章

TensorFlow代码逻辑 vs PyTorch代码逻辑

文章目录 一、TensorFlow(一)导入必要的库(二)加载MNIST数据集(三)数据预处理(四)构建神经网络模型(五)编译模型(六)训练模型&#xf…

@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", …

Apache APISIX 介绍

Apache APISIX 是一个动态、实时、高性能的云原生API网关,属于Apache软件基金会旗下的项目。以下是对Apache APISIX的详细介绍: 一、基本概述 定义:Apache APISIX是一个提供丰富流量管理功能的云原生API网关。功能:包括负载均衡…

git出现Permission denied问题

Warning: Permanently added ‘icode.baidu.com,10.11.81.103’ (RSA) to the list of known hosts. Permission denied (baas,keyboard-interactive,publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the…

nodejs操作excel文件实例,读取sheets, 设置cell颜色

本代码是我帮客户做的兼职的实例,涉及用node读取excel文件,遍历sheets,给单元格设置颜色等操作,希望对大家接活有所帮助。 gen.js let dir"D:\\武汉烟厂\\山东区域\\备档资料\\销区零售终端APP维护清单\\走访档案\\2024年6月…

Spring之事务失效的场景

Spring事务失效的场景 异常捕获处理:自己处理了异常,没有抛出。解决:手动抛出抛出检查异常:配置rollbackFor属性为Excetion非public方法导致事务失效,改为public 1、异常捕获处理 示例: 张三1000元&#…

7月形势分析-您下一步该如何做,才能走出困境?

马上工程项目,再有三五天就要结束的了。即便推后也不会超过一周时间了。所以需要考虑将来干啥呢?  一方面就是继续去济宁做建筑工程的活。管吃住,但是因为至亲之间,难免咋说呢,总之还是不太舒服的样子。管事情多&…

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…

【数据结构 - 时间复杂度和空间复杂度】

文章目录 <center>时间复杂度和空间复杂度算法的复杂度时间复杂度大O的渐进表示法常见时间复杂度计算举例 空间复杂度实例 时间复杂度和空间复杂度 算法的复杂度 算法在编写成可执行程序后&#xff0c;运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏&…

[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中窗体绘制相关的内容…

ECharts 快速入门

文章目录 1. 引入 ECharts2. 初始化 ECharts 实例3. 配置图表选项4. 使用配置项生成图表5. 最常用的几种图形5.1 柱状图&#xff08;Bar Chart&#xff09;5.2 折线图&#xff08;Line Chart&#xff09;5.3 饼图&#xff08;Pie Chart&#xff09;5.4 散点图&#xff08;Scatt…

如何完成域名解析验证

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

Linux内核 -- 多线程之完成量completion的使用

Linux Kernel Completion 使用指南 在Linux内核编程中&#xff0c;completion是一个用于进程同步的机制&#xff0c;常用于等待某个事件的完成。它提供了一种简单的方式&#xff0c;让一个线程等待另一个线程完成某项任务。 基本使用方法 初始化 completion结构需要在使用之…

顺序串算法库构建

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