struct结构体、union联合体和枚举

目录

一、结构体的声明和使用

1.1 结构体正常声明和创建

1.2 结构体特殊声明

1.3 结构体的自引用

二、结构体内存对齐

2.1 对齐规则

2.2 #pragma修改

三、结构体传参

四、结构体位段

4.1 位段内存分配

4.2 位段内存应用

五、结构体中的柔性数组概念

六、union联合体

6.1 union联合体声明、使用和特点

6.2 union联合体在内存的存储

七、枚举类型

7.1 枚举类型的声明

7.2 枚举类型的优点


一、结构体的声明和使用

1.1 结构体正常声明和创建

        struct用来声明结构体变量,格式为struct 名字{内部成员};(这里有分号)后面还能直接设置全局变量,直接写变量名,比如struct Stu{};然后初始化一个变量名struct Stu s1,这个s1就是结构变量(struct Stu是一个结构体的类型是一个整体,而s1是这个变量名)。使用时需要使用{}里面用来设置初始化的,如果struct里面还有一个结构体,那么初始化时{}这个括号内也要再加一个括号给他初始化,引用时可以不按顺序来设置初始化,这时候就需要一个操作符“.”点这个操作符,格式为.内部变量名=初始化。当然还可以修改初始化内容就是结构体名.内部变量名=修改内容,但是数组就需要一个库函数strcpy(string.h),strcpy(结构体名.内部变量,修改内容)对于内部成员为指针,引用时可以用“->”指针取向操作符。

1.2 结构体特殊声明

        对于特殊声明就是没有名字(指的是结构体名字),而如果没有名字的结构体内成员是一模一样的两个结构体,两个结构体中设置指针,将一个指针赋给另一个结构体的指针时,编译器会报警告(编译器默认这两个结构体指针类型是不一样的)。

#include<stdio.h>
struct
{char str[20];int a;char b;
}*s1,a;
struct
{char str[20];int a;char b;
}*s2;
int main()
{s1 = &a;s2 = s1;return 0;
}

 报警告!!!

匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。

1.3 结构体的自引用

        结构体的自引用就是链表,通过指针引用结构体进行内容访问寻找数据。

        需要定义链表的节点

struct Stu
{char name[20];//数据域struct Stu* nest;//地址域
};

                                                                    ↑↑↑

                                                                正确方式 

struct Stu
{char name[20];struct Stu nest;
};

                                                                  ↑↑↑

                                                              错误方式

扩展:数据结构,是描述数据在内存中的存储结构。结构体链表(结构体自引用),通过相同的节点进行连接,上一个节点有下一个节点的地址,而下个节点有下下个节点的地址。

        这里夹杂了 typedef 对匿名结构体类型重命名 ,在函数中自引用如果使用不到位会报错,不能只写重命名的名字到里面,而是要写全,才能设置为指针域。

#include<stdio.h>
typedef struct node
{int a;//node* next;//因为上面typedef重命名还没命名完,所以这里需要写全struct node* nest;//所以还需要自己来写
}node;//这里typedef已经重定义完了int main()
{return 0;
}

 

二、结构体内存对齐

2.1 对齐规则

        第一条:结构体内部的第一个任何成员是在偏移量为0位置

        第二条:结构体要对齐到最小对齐数的整数倍(最近的整数倍);最小对齐数为成员类型的字节数与编译器默认的对齐数的最小对齐数。这里以我的编译器vs来举例,该编译器的默认为8,我在结构体内部用了一个char一个int类型成员(按左到右按顺序)按照第一条char位于偏移量为0,而int类型的话,那就是要位于偏移量为4的位置了(int类型4个字节,默认8,最小为4)。

        第三条:结构体总大小要为最大对齐数(这里指的是成员内最大对齐数,char最小是1,int最小是4,所以最大对齐数为4)的整数倍(最近)。同样的举一个例子来说明 内部有三个成员(按顺序)char、int和char类型的成员

        第四条:嵌套结构体时,计算结构体总大小时,最大对齐数要和嵌套结构体的内部成员一起计算,嵌套结构体时可以将嵌套的那个结构体当作结构体内的一个成员,规则都和前面3条符号,就是计算总大小时的最大对齐数要配合嵌套结构体的内部成员。

#include<stdio.h>
struct test1
{char a;double b;char c;int d;
};
struct test2
{int e;struct test1;//默认8,这个成员字节为24,最小为8
};
int main()
{printf("%zd\n", sizeof(struct test2));return 0;
}

 

 对于结构体的内存对齐一般是为了用空间换取时间的手段,方便了内存的读取(如果不对齐,可能需要读取两次,对齐只需读一次),提高读取效率,不过在对于这个规则,我们不能一味的用大量的空间去换取时间,可以将一些小的类型写在一起(相同类型),避免了大量空间的浪费,也确保了读取效率。

计算偏移量,一般用offsetof来表示宏,可计算结构体成员相较于结构体起始位置的偏移量,他需要头文件stddef.h。用法为offsetof(结构体类型,结构体内成员) 。

2.2 #pragma修改

        这个定义是用于改变默认对齐数的(改变的是编译器),一般编译器默认是8,改变为4或者2,也会影响结构体大小。

这里pragma要配合pack使用。不过一般修改都是以2的次方数进行修改的。 

三、结构体传参

        结构体传参有两种方式,一种是传值(结构体变量),一种是传址(传地址)。

#include<stdio.h>
struct Stu
{char name[20];int age;
};
void print2(struct Stu* s1)//传址
{printf("%s\n", s1->name);
}
void print1(struct Stu s1)//传值
{printf("%s\n", s1.name);
}
int main()
{struct Stu s1 = { "zhangsan",20 };print1(s1);print2(&s1);return 0;
}

        一般我们写结构体的时候会选择传址调用,传值调用消耗内存太大了,如果结构体内部有一个很大的数组,那么这个结构体开辟空间会很大,不仅如此形参和实参的调用都会开辟这么多空间。传值调用,因为指针字节要么是4个字节要么是8个字节,就算开辟也不会占很大空间,所以一般会使用传址调用。

四、结构体位段

4.1 位段内存分配

        结构体位段,用于节省空间方便传输等。结构体内的成员必须是int、unsigned int、signed int类型,不过在c99中其他成员类型也是可以。

struct A
{int a : 2;int b : 5;int c : 10;int d : 30;
};

        这就是一个位段,后面接的是比特数 

        内存中的位段是

这里如果以上空间都正常使用的话,一共开辟2个字节空间,但是实际不是这样,因为他们不够连续在一起,就会再开辟(因为不是从左到右,这里是从右到左) 

4.2 位段内存应用

                位段在网络传输过程中用到很多位段,因为我们在传输的时候会考虑到传输速度和简单方面考虑可以类比卡车。

像第二张,这种小车就能够进行超车,效率会很快。

位段是没有跨平台性的,所以我们可以为一个平台专门设置位段进行节约空间。,不过位段也有缺点,就是不能取地址吗,所以就不能通过scanf来修改内的内容,只能先赋值在位段

五、结构体中的柔性数组概念

        柔性数组是位于结构体内最后的一位成员的数组,可以没有大小。特点就是计算结构体总大小时,不会计算数组大小,这个柔性数组是可以通过动态内存来确定数组大小(更加灵活),这个我后面会和动态内存一起讲。

六、union联合体

6.1 union联合体声明、使用和特点

        union联合体声明和时候方法是和struct结构体是一样的,也有匿名联合体,唯一的区别就是在计算时总大小时是不一样的,union联合体大小是去内部成员内最大字节,其他的会重叠内存,改变一个字节就会影响另一个数。联合体相比结构体会更加节约空间。

//在表示商品共同属性和特殊属性时也可以使用union联合体
#include<stdio.h>
struct gift_list
{int stock_number;//库存double price;//定价int item_type;//商品类型union{struct{char tille[20];//书名char author[20];//作者名int num_pages;//页数}book;struct{char design[20];//设计}mug;struct{char design[20];//设计int colors;//颜色int sizes;//尺寸}shirt;};//这里都用匿名,是因为都只使用一次
}item;
//这样的设计就能节约空间(相比较全部用struct结构体)
int main()
{return 0;
}

6.2 union联合体在内存的存储

        union联合体在内存中是内存重叠。

        这里用判断大小端来举例

#include<stdio.h>
union A
{char a;int b;
};
int check_sys()
{union A n = { 0 };n.b = 1;if (n.a == 1){return 1;}else{return 0;}
}
int main()
{int ret =check_sys();if (ret == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}

                                                                这里再来一个例子

#include<stdio.h>
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };un.i = 0x11223344;un.c = 0x55;printf("%x\n", un.i);return 0;
}

七、枚举类型

7.1 枚举类型的声明

        枚举一般用于列举,比如生活中的星期、性别、月份和三原色等。声明和使用和结构体和联合体类似。

enum sex
{boy,girl,secret
};//格式和结构体和

内部的值都是枚举常量,只能在内部改变。内部不赋值,那就默认从0开始递增。

7.2 枚举类型的优点

        枚举的优点1.方便代码可读性,可维护性。2.相较于用#define定义的常量,枚举有类型的会更加严谨。3.使用方便,可以一次性列举多个常量。4.枚举是遵循定义域的,在函数中定义,就只能在函数中使用

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

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

相关文章

大模型本地部署系列(2) Ollama部署DeepSeek-R1

成功运行截图 部署步骤 我们进入到ollama的官网&#xff1a; Ollama​ollama.com/​编辑 找到上方的Models &#xff0c;然后点击 此时会跳转到模型列表页面&#xff1a; 点击 deepseek-r1 链接进去&#xff0c;此时我们会看到下拉框中有各个版本的大模型&#xff0c;越往后…

绘制动态甘特图(以流水车间调度为例)

import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np from matplotlib import cm# 中文字体配置&#xff08;必须放在所有绘图语句之前&#xff09; plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Fa…

PyTorch实现线性回归的基础写法与封装API写法

目录 1. 基础写法 1.1导包 2.2加载读取数据 2.3原始数据可视化(画图显示) 2.4线性回归的(基础)分解写法 2.5定义训练过程 2.PyTorch实现 线性回归的封装写法(实际项目中的常用写法) 2.1创建线性回归模型 2.2定义损失函数 2.3定义优化器 2.4定义训练过程 1…

python 常用的6个爬虫第三方库

Python中有非常多用于网络数据采集的库&#xff0c;功能非常强大&#xff0c;有的用于抓取网页&#xff0c;有的用于解析网页&#xff0c;这里介绍6个最常用的库。 1. BeautifulSoup BeautifulSoup是最常用的Python网页解析库之一&#xff0c;可将 HTML 和 XML 文档解析为树形…

基于BP神经网络的杂草智能识别系统(杂草识别、Python项目)

基于BP神经网络的杂草智能识别系统 项目介绍 本项目是一个基于PyQt5和BP神经网络的杂草智能识别系统。系统通过图像处理和神经网络技术&#xff0c; 能够识别8种不同的杂草类别。用户可以通过上传图片&#xff0c;系统会自动识别图片中的杂草类别&#xff0c;并显示识别结果和…

Python3笔记之号称替代pip的uv包管理器

uv是什么&#xff1f; uv&#xff0c;这是一个由 Astral 团队开发的极快速的Python包和项目管理工具&#xff0c;用Rust语言编写。它集成了多种功能&#xff0c;旨在替代pip、pip-tools、pipx、poetry、pyenv、twine、virtualenv等多个工具&#xff0c;提供更高效、更全面的Py…

IT管理思路

甲方CIO和IT管理者-如何做好组织级IT能力提升_哔哩哔哩_bilibili

ChatGPT的GPT-4o创建图像Q版人物提示词实例展示

最近感觉GPT-4o发布的新功能真的强大&#xff0c;所以总结了一些提示词分享给大家&#xff0c;大家可以去试试&#xff0c;玩法多多&#xff0c;可以用GPT-4o生成图片&#xff0c;然后用可灵进行图生视频&#xff0c;就能去发布视频了&#xff01;接下来和笔者一起来试试&#…

Transformer Decoder Block的几个优化方案

写在前面 在大型语言模型(LLM)的演进浪潮中,Transformer 架构凭借其强大的并行计算能力和对长距离依赖的出色捕捉,奠定了核心地位。然而,标准的 Transformer Decoder Block 遵循着一种相对固定的模式:先进行自注意力(Self-Attention)捕捉上下文信息,再通过前馈神经网…

五种IO模型与select和poll分别实现多路转接

五种IO模型与select和poll分别实现多路转接 何为IO 不论是在前面文件部分&#xff0c;还是后面的网络部分&#xff0c;IO都是非常常见的。但是当时只是简单对IO进行提及&#xff0c;并没有对IO的本质进行介绍。那么到底何为IO&#xff1f;IO全称为输入和输出&#xff0c;而任…

单例模式的写法(保证线程安全)

1. 引言 1.1 什么是单例模式&#xff1f; 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 核心思想&#xff1a;控制实例化过程&#xff0c;避免重复创建对象。 1.2 为什么…

C++ 环境设置

C++ 环境设置 引言 C++作为一种高性能的编程语言,广泛应用于系统软件、游戏开发、实时系统等领域。为了能够顺利进行C++编程,我们需要在计算机上配置合适的开发环境。本文将详细讲解如何在Windows、macOS和Linux系统中设置C++开发环境。 Windows系统下C++环境设置 1. 安装…

【Kafka基础】ZooKeeper在Kafka中的核心作用:分布式系统中枢神经系统

在分布式系统的世界里&#xff0c;协调和管理多个节点间的状态是一项复杂而关键的任务。Apache Kafka作为一款高性能的分布式消息系统&#xff0c;其设计哲学是"专为单一目的而优化"——即高效处理消息流。为了实现这一目标&#xff0c;Kafka选择将集群协调管理的重任…

<《AI大模型应知应会100篇》第8篇:大模型的知识获取方式及其局限性

第8篇&#xff1a;大模型的知识获取方式及其局限性 摘要 大模型&#xff08;如GPT、BERT、Qwen、DeepSeek等&#xff09;凭借其卓越的自然语言处理能力&#xff0c;已经成为人工智能领域的明星。然而&#xff0c;这些模型“知道”什么&#xff1f;它们如何获取知识&#xff1f…

ESModule和CommonJS在Node中的区别

ESModule console.log(require);//>errorconsole.log(module);//>errorconsole.log(exports);//>errorconsole.log(__filename);//>errorconsole.log(__dirname);//>error全部报错commonjs console.log(require);console.log(module);console.log(exports);co…

Spring Boot 配置文件加载优先级全解析

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot 配置文件加载优先级全解析 Spring Boot 的配置文件加载机制是开发者管理不同环境配置的核心功能之一。其通过外部化配置&#xff08;Externaliz…

2025 年陕西消防设施操作员考试攻略:历史文化名城的消防传承与创新​

陕西拥有丰富的历史文化遗产&#xff0c;众多古建筑分布其中&#xff0c;同时也在不断推进现代化建设&#xff0c;消防工作面临传承与创新的双重任务&#xff0c;这在考试中也有所体现。​ 考点融合与特色&#xff1a;一方面&#xff0c;古建筑的消防保护是重点&#xff0c;包…

【Unity网络编程知识】C#的 Http相关类学习

1、搭建HTTP服务器 使用别人做好的HTTP服务器软件&#xff0c;一般作为资源服务器时使用该方式&#xff08;学习阶段建议使用&#xff09;自己编写HTTP服务器应用程序&#xff0c;一般作为Web服务器或者短连接游戏服务器时使用该方式&#xff08;工作后由后端程序员来做&#…

Android Studio - 解决 Please Select Android SDK

一、出现的问题 点击 Run 后弹窗&#xff0c;图一位置出现图二提示。 二、解决办法 进入 Tools -> SDK Manager&#xff0c;在 Android SDK Location 点击 Edit&#xff0c;一直 Next 就解决了。

UE5学习笔记 FPS游戏制作44 统一UI大小 sizeBox

如果我们希望多个类似的UI大小一样&#xff0c;例如不同菜单的标题&#xff0c;可以使用sizeBox组件 我们在标题控件上&#xff0c;用sizeBox包裹所有子物体 然后指定他的最小宽高&#xff0c;或最大宽高 如果指定的是最小宽高&#xff0c;当子元素&#xff08;如图片&#xf…