C语言结构体介绍(超详细)

文章目录

  • 每日一言
  • 结构体是什么?
  • 为什么要使用结构体?
  • 如何使用结构体?
    • 结构体的定义
    • 结构体的声明
    • 如何访问结构体中的成员
  • 结构体内存对齐
    • 什么是结构体内存对齐
      • 对齐规则
        • 修改默认对齐数
    • 为什么存在结构对齐
  • 总结
  • 结语

每日一言

Develop your imagination – you can use it to create in your mind what you hope to create in your life.
发展你的想像力 – 你可以用它在心里创造你想在现实生活创造的东西。


结构体是什么?

结构体是一种自定义的数据类型,可以包含多个不同类型的数据成员,并可以根据这些成员进行组合和访问。结构体可以用于表示一个具有多个属性的实体或对象,例如一个人的姓名、年龄和性别,一个车辆的品牌、型号和颜色,等等。

为什么要使用结构体?

C语言已经为我们提供了许多的内置类型,如:int、long、float、double、char、short等,但这些类型只能描述相对单一的事物。
假如我要描述一个人,人是一个相对复杂的事物,他有姓名、年龄、性别、身份证号、体重、电话号码等属性。这时如果只用上面给出的类型是很难描述一个人的所有信息的。

如何使用结构体?

结构体的定义

struct 结构体名称 {
    数据类型 变量名1;
    数据类型 变量名2;
    // ...
};

例如用结构体描述一个人:

struct Person {
    char name[20];//名字
    int age;//年龄
    char gender;//性别
    char id_card[18];//身份证号
    float weight;//体重
    char phone[11];//电话
};

结构体的声明

声明结构体变量的格式如下:

struct 结构体名 变量名;

例如,声明一个名为awa,年龄为18岁,性别为男,身份证号为666666,体重为60.2,电话为1234567的人:

方式一
声明结构体变量时直接定义结构体

代码如下:

struct Person {
    char name[20];//名字
    int age;//年龄
    char gender;//性别
    char id_card[18];//身份证号
    float weight;//体重
    char phone[11];//电话
}awa = {"awa",18,'M',"666666",60.2,"1234567"};

方式二
先定义结构体类型,再声明结构体变量

代码如下:

struct Person {
    char name[20];//名字
    int age;//年龄
    char gender;//性别
    char id_card[18];//身份证号
    float weight;//体重
    char phone[11];//电话
};

struct Person awa = {"awa",18,'M',"666666",60.2,"1234567"};

两种方式的本质区别在于第一种方式在定义结构体变量的同时也定义了结构体类型,而第二种方式分别定义了结构体类型和结构体变量。而在实际应用中,通常会使用第一种方式,代码会更加简洁明了。 C语言也支持在结构体中嵌套定义其他结构体。

如何访问结构体中的成员

我们依然以上面的awa为例,如何在屏幕上打印出awa的电话呢?
我们有两种方法:

法一:
通过点操作符来访问结构体成员。

代码如下:

printf("awa的电话是:%s\n", awa.phone);

法二:
通过指针操作符来访问结构体成员。

代码如下:

struct Person *p;//定义一个指针p,它的类型是struct Person。
p = &awa;//将p指向结构体变量awa的地址。
printf("awa的电话是:%s\n", p->phone);

结构体内存对齐

现在我们对结构体有了大致的了解,接下来我们来谈一谈结构体是如何在内存中存储的。只有了解了它的本质,我们用起来就更加得心应手。

什么是结构体内存对齐

内存对齐是指将数据存储在内存中时,按照某种规则对其进行填充,使其在访问时的速度更快。这主要是因为CPU的读取速度与地址对齐有关。

对齐规则

  1. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  2. 对齐数 = 编译器默认的一个数与该成员变量大小的较小值
  3. 结构体总是大小为最大对齐数的整数倍
  4. 如果是嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍

例:
求AA_t 所站的字节大小(假如编译器默认对齐数为8字节)

typedef struct{
  int a;
  char b;
  short c;
  short d;
}AA_t;

计算过程:
在这里插入图片描述

注意:
VS中默认的对齐数为8
Linux中gcc没有默认对齐数,对齐数就是成员自身的大小

修改默认对齐数

#pragma 这个预处理指令可以改变编译器的默认对齐数

例:
#pragma pack(1)
设置默认对齐数为1

#pragma pack()
取消设置的默认对齐数

一般不建议修改默认对齐数,它会导致许多问题。

1.可能会破坏结构体的内存对齐,导致结构体成员的访问速度变慢,因为不是按照CPU的最佳对齐方式进行的。

2.可能会增加内存的浪费。如果对齐数太小,内存对齐不足,会导致内存浪费,因为需要加入一些填充字节来填充对齐差距。

3.可能会影响平台的可移植性。不同的平台对内存对齐的要求可能不同,因此在不同的平台上运行代码时可能会出现错误或不一致的结果。

4.可能会使代码变得难以维护,并且会增加调试难度。更改默认对齐数通常是非标准的做法,开发人员可能需要花费更多时间来解决由此引起的问题。

为什么存在结构对齐

通过对结构体进行对齐,可以保证每个结构体成员访问时都能够在一个内存块中连续访问,提高了代码的执行效率。同时,结构体对齐也能够减少内存碎片的产生,进一步提高内存的利用效率。

注意:
内存对齐可以提高数据访问的效率,但同时也会增加内存空间的浪费。因此,在设计结构体时,需要权衡对齐对空间利用率和访问效率的影响,以达到最优的设计。
通常我们尽量让占用空间小的成员集中在一起

总结

  1. 结构体的定义:需要使用关键字struct,语法格式如下:
struct 结构体名称 {
    数据类型 变量名1;
    数据类型 变量名2;
    // ...
};
  1. 成员变量的定义:可以是基本数据类型、指针类型、数组类型等。定义时需要指明变量名和数据类型。

  2. 结构体的大小:结构体的大小是所有成员变量大小的累加,需要考虑对齐方式和填充字节。

  3. 结构体的初始化:可以采用两种方式进行初始化,一种是在定义时赋值,另一种是通过赋值运算符对结构体对象进行初始化。

  4. 结构体的成员访问:可以通过".“或”->“运算符进行成员访问,”.“用于访问结构体对象的成员,”->"用于访问指向结构体的指针的成员。

  5. 结构体的传参:可以将结构体作为函数参数传递,可以通过传值或传指针的方式进行传参。

  6. 结构体的对齐方式:需要指明对齐方式,可以通过#pragma pack指令或__attribute__((packed))关键字来进行设置。


结语

请给自己些耐心,一口吃不成胖子。
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!


都看到这里啦!真棒(*^▽^*)

可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家

编程小白写作,如有纰漏或错误,欢迎指正


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mabatis处理异常屏蔽SQL返回前端全局异常捕获处理

文章目录 Mabatis处理异常屏蔽SQL返回前端全局异常捕获处理结论1 java异常体系2 Spring框架异常处理3 定位Spring框架转化为哪种unchecked异常3.1 捕获RuntimeException定位Spring框架转化抛出的异常类3.2 进一步查看包名判断3.3 识别MyBatisSystemException下级实现3.3 识别My…

postman常用脚本

在参数中动态添加开始时间和结束时间的时间戳 1.先在collection中添加参数,这里的作用域是collection,也可以是其他的任何scope 2.在Pre-request Script 中设定开始时间和结束时间参数,比如昨天和今天的时间戳,下面是js代码 con…

【Qt开发流程】之对象模型1:信号和槽

Qt对象模型 标准c对象模型为对象范型提供了非常有效的运行时支持。但是它的静态特性在某些问题领域是不灵活的。图形用户界面编程是一个既需要运行时效率又需要高度灵活性的领域。Qt通过结合c的速度和Qt对象模型的灵活性提供了这一点。 Qt将这些特性添加到c中: 一个非常强大的…

DNS协议(DNS规范、DNS报文、DNS智能选路)

目录 DNS协议基本概念 DNS相关规范 DNS服务器的记录 DNS报文 DNS域名查询的两种方式 DNS工作过程 DNS智能选路 DNS协议基本概念 DNS的背景 我们知道主机通信需要依靠IP地址,但是每次通过输入对方的IP地址和对端通信不够方便,IP地址不好记忆 因此提…

【国产云 OS】KoyarchOS:实现稳定性与兼容性的行业标杆操作系统

文章目录 一、前言二、CentOS 谢幕、国内操作系统崛起2.1 CentOS 的前世今生2.2 创新操作系统崛起 三、浪潮信息 KeyarchOS 操作系统3.1 认识 KeyarchOS 操作系统3.2 KeyarchOS 产品优势3.2.1 稳定可靠3.2.2 广泛兼容3.2.3 平滑迁移3.2.4 场景增强 3.3 KeyarchOS 支持多场景优化…

CAD画图-模型和布局区别,视图命令MV使用(用于局部放大显示)

模型和布局的图像区别 模型的图像: 是我们常编辑的cad文件,我们可以对里面内容进行编辑和测量等操作 布局的图像:为了可以更好的看到每个部件的相对位置,但对于里面的点位的标注就不行了,但可以对图像中的某些部位进行…

思维模型 移情效应

本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。情感迁移,爱屋及乌。 1 移情效应的应用 1.1 移情效应在市场营销中应用-多芬(Dove)“真美运动” 多芬(Dove)是一家知名的个人护理…

一起学习:大型语言模型(LLM)中的QKV(Query, Key, Value)和多头注意力机制

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

CentOS最小化安装后怎么转图形界面/可视化桌面?

文章目录 1、命令行和图形界面切换方式一方式二 2、最小化安装转桌面1-设置网络2-测试网络3-更新文件4-安装图形5-查看默认6-设置默认 界面效果参考视频 1、命令行和图形界面切换 如果安装的是最小化,那么init 5 (进入图像化桌面)命令是无效的 方式一 1.如果在命…

基于STM32 HAL库的光电传感器驱动程序实例

本文将使用STM32 HAL库编写一个光电传感器的驱动程序示例。首先,我们会介绍光电传感器的工作原理和应用场景。然后,我们将讲解如何选择合适的STM32芯片和光电传感器组合。接下来,我们会详细介绍使用STM32 HAL库编写光电传感器驱动程序的基本步…

【Rust日报】2023-12-04 slint 成功案例

slint 成功案例 SK Signet是美国领先的电动车充电解决方案提供商,推出了适用于其电动车充电桩的新型HMI(人机界面)。支持15英寸和32英寸触摸屏。 该HMI由Slint制作,为充电站运营商提供了额外的商机。SK Signet经理Sang-Baek Lee表…

【ArcGIS Pro微课1000例】0049:根据坐标快速定位(创建点位)的常见方法

文章目录 一、转到XY1. 闪烁位置2. 平移3. 标记位置二、定位1. 坐标定位2. 添加到图形3. 添加至要素类三、添加XY坐标四、创建点要素一、转到XY 举例:经纬度坐标:113.2583286东, 23.1492340北 。 1. 闪烁位置 输入坐标,点击闪烁位置工具,即可在对应的位置出现一个绿色闪烁…

19、pytest通过mark标记测试函数

官方实例 [pytest] markers slow:marks tests as slow(deselect with -m "not slow")serial# content of test_mark.py import pytestpytest.mark.slow def test_mark_function():print("test_mark_function was invoked")assert 0解读与实操 通过使用p…

同源策略和跨域介绍

浏览器的同源策略阻止读取来自不同来源的资源。这种机制阻止恶意站点读取另一个站点的数据,但它也阻止合法使用。 一般情况下,我们可以通过两种方式解决浏览器的同源策略,JSONP和CORS,CORS解决方案更为通用(推荐)。

生鲜蔬果展示预约小程序作用是什么

线下生鲜蔬果店非常多,对商家来说主要以同城生意为主,而在互联网电商的发展下,更多的商家会选择搭建私域商城进行多渠道的销售卖货和拓展,当然除了直接卖货外,还有产品纯展示或预约订购等需求。 但无论哪种模式&#…

获得矩阵对角线元素的索引 numpy.diag_indices_from()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 获得矩阵对角线元素的索引 numpy.diag_indices_from() [太阳]选择题 请问关于以下代码的选项表述错误的是? import numpy as np a np.array([[1, 2, 3], [4, 5, 6…

2024年网络安全行业前景和技术自学

很多人不知道网络安全发展前景好吗?学习网络安全能做什么?今天为大家解答下 先说结论,网络安全的前景必然是超级好的 作为一个有丰富Web安全攻防、渗透领域老工程师,之前也写了不少网络安全技术相关的文章,不少读者朋…

虹科Pico汽车示波器 | 汽车免拆检修 | 2018款东风风神AX7车发动机怠速抖动、加速无力

一、故障现象 一辆2018款东风风神AX7车,搭载10UF01发动机,累计行驶里程约为5.3万km。该车因发动机怠速抖动、加速无力及发动机故障灯异常点亮而进厂维修,维修人员用故障检测仪检测,提示气缸3失火;与其他气缸对调点火线…

Kafka 消费者 API 指南:深入探讨消费者的实现与最佳实践

Kafka 消费者 API 是连接应用程序与 Kafka 集群之间的关键接口,用于从 Kafka 主题中拉取消息并进行处理。本篇文章将深入探讨 Kafka 消费者 API 的核心概念、用法,以及一些最佳实践,帮助你构建高效、可靠的消息消费系统。 1. Kafka 消费者 A…

[组合数学]LeetCode:2954:统计感冒序列的数目

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 题目 给你一个整数 n 和一个下标从 0 开始的整数数组 sick ,数组按 升序 排序。 有 n 位小朋友站成一排,按顺序编号为 0 到 n - 1 。数组 sick 包含一开始得了感冒的小朋友的位置。如果位…