结构体类型详细讲解(附带枚举,联合)

前言:

如果你还对结构体不是很了解,那么本篇文章将会从 为什么存在结构体,结构体的优点,结构体的定义,结构体的使用与结构体的大小依次介绍,同样会附带枚举与联合体

 

目录

 为什么存在结构体:

 结构体的优点

结构体的定义 

结构体的使用

方法一:

方法二   函数传值打印

方法三  函数传址打印   两种打印方法

第二种是利用->  这里的 ->就相当于(*).

方法四  跟方法三差不多,不利用函数打印 

结构体的typedef 

 结构体的大小计算

 ⾸先得掌握结构体的对⻬规则:

1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处

 2.其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8

Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩

3.结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。

4.如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

先解决对其数问题

 枚举

 枚举的使用案例

联合体(也叫共用体)


 为什么存在结构体:

当一个整体由多个数据构成时,于是人们就创造了数组,我们用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。 ☀ 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。 ☀ 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的

 结构体的优点

 

  • 可以在一个结构中声明不同的数据类型。
  • 相同结构的结构体变量是可以相互赋值的。
  • 结构体的存储方式可以提高CPU对内存的访问速度。
  • 结构体可以将同一对象的多个数据类型存储在一起,方便数据的存储和处理。
  • 可以通过结构体变量名和成员名来访问数据。
  • 可以定义结构体数组,方便批量处理数据。

那么有有优点就会有缺点:

  • 如果项目的复杂性增加,管理所有数据成员就变得很困难 。
  • 对程序中的一个数据结构进行更改需要在其他几个地方进行更改。 所以很难跟踪所有的变化。
  • 结构体需要更多的存储空间,因为它为所有数据成员分配内存,甚至速度更慢。
  • 结构体占用更多存储空间,因为它为所有不同的数据成员提供内存,而联合仅占用最大数据大小参数所需的内存大小,并且与其他数据成员共享相同的内存。

结构体的定义 

 一般结构体定义便是如下

struct stu
{//变量成员
};

这里的struct是必不可少的部分,而stu是我们自拟定的,里面便是填充的变量成员

这个结构体就是struct stu类型的

同理下面这个结构体就是struct st类型的

struct st
{//变量成员
};

 这时候我们便可以在里面填充成员

比如这样

struct st
{int a;char b;struct st* ps;//也可以填充这个类型的指针
};

那么结构体定义完后,我们开始讲解怎么去使用

结构体的使用

这里的s为变量名 

struct st
{int a;char b; 
};
int main()
{struct st s = { 10,'b' };//初始化return 0;
}

 接下来介绍打印

方法一:

struct st
{int a;char b; 
};
int main()
{struct st s = { 10,'b' };//初始化printf("%d %c", s.a, s.b);return 0;
}

 

方法二   函数传值打印

struct st
{int a;char b; 
};
void print(struct st ps)
{printf("%d %c", ps.a, ps.b);
}
int main()
{struct st s = { 10,'b' };//初始化print(s);return 0;
}

 

方法三  函数传址打印   两种打印方法

第一种的打印是利用解引用

第二种是利用->  这里的 ->就相当于(*).

struct st
{int a;char b; 
};
void print(struct st* ps)
{printf("%d %c\n", (*ps).a, (*ps).b);printf("%d %c\n", ps->a, ps->b);
}
int main()
{struct st s = { 10,'b' };//初始化print(&s);return 0;
}

方法四  跟方法三差不多,不利用函数打印 

struct st
{int a;char b; 
};
int main()
{struct st s = { 10,'b' };//初始化struct st* ps = &s;printf("%d %c\n", (*ps).a, (*ps).b);printf("%d %c\n", ps->a, ps->b);return 0;
}

结构体的typedef 

 当一个结构体类型的类型名过于长的时候,我们不免过于不想去写,这时候就可以用typedef

(重命名)使用起来很简单

typedef struct st
{int a;char b; 
}st;
int main()
{struct st s = { 10,'b' };//初始化//等价于st s = { 10,'b' };//return 0;
}

 结构体的大小计算

先举例一个代码

代码跑出来这个结构体大小是8 

那么怎么计算的呢?  其原理就是对其原则

 ⾸先得掌握结构体的对⻬规则:

1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处

 2.其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8

Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩

3.结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。

4.如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

 

我们计算一下这个结构体大小 

struct S1
{char c1;int i;char c2;
};
printf("%d\n", sizeof(struct S1))

先解决对其数问题

char    自身对齐数为1  vs上默认对齐数为8    实际取小的   那么最后为1

int 为4 

 偏移量

在C语言中,偏移量通常指的是结构体中成员变量相对于结构体起始地址的偏移量。假设有一个结构体定义如下:

struct Person {int id;char name[20];int age;
};

假设struct Person p;是一个Person类型的结构体变量,我们可以通过&p.id&p.name&p.age来获取各个成员变量的地址。偏移量就是从结构体起始地址到成员变量地址的字节偏移量。

例如,假设&p表示结构体p的起始地址,&p.id表示id成员变量的地址,那么&p.id - &p就是id相对于结构体起始地址的偏移量。在C语言中,可以使用指针和强制类型转换来计算偏移量,例如:

int offset = (char *)&p.name - (char *)&p;

 这样就可以得到name成员变量相对于结构体p的偏移量。偏移量在一些底层编程中经常用来访问结构体中的特定成员变量,尤其是在处理二进制数据或者硬件寄存器时非常有用。

画图表示如下

 那么我们进行利用图进行计算

typedef struct st
{char c1;int i;char c2; 
}st;
int main()
{printf("%zd", sizeof(st));return 0;
}

第一个char偏移量为0放于第一个,int放于偏移量为4的整数倍数处  ,最后一个char偏移量为1,放于1的整数倍数处,

用图表示如下

图上的大小一共占了9个字节,

然后我们进行最后一步 最大对齐数为4  而9不是最大对齐数的整数倍   所以要浪费3个字节补充该结构体大小到12;

那么最大怎么算了就可以解答上面那个问题为什么是8

//练习3 
struct S3
{double d;char c;int i;
};
printf("%d\n", sizeof(struct S3));
//练习4-结构体嵌套问题 
struct S4
{char c1;struct S3 s3;double d;
};
printf("%d\n", sizeof(struct S4));

答案分别是16    32         

 枚举

 在《C语言深度剖析》这本书中留有一个问题,枚举变量的大小是多少?

大家猜一下大小为多少

enum Color
{GREEN = 1,RED,BLUE,GREEN_RED = 10,GREEN_BLUE,sss,
}c;
int main()
{printf("%zd", sizeof(c));
}

答案是4,为啥呢?

因为,枚举变量的取值为花括号内的任意一个值(有且只能有其中一个值),而这个值是int型的,在X86系统中,int型的数据占内存4个字节。所以sizeof(c) = 4,也就是枚举变量的值为4。

 枚举的使用案例

当我们写菜单的时候,会用到switch语句

当我们写case是一般会用到case 1: case 2:

但如果功能一旦多我们就会分不清该case  要实现哪一项功能

这时候就可以用到枚举  就比如通讯录

enum option
{EXIT,//等价于0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW, //5SORT,//6SAVE,//7
};void menu()
{printf("**************************************\n");printf("*****    1.add        2.del      *****\n");printf("*****    3.search     4.modify   *****\n");printf("*****    5.show       6sort      *****\n");printf("*****    7.save       0.exit     *****\n");printf("**************************************\n");
}
int main()
{do {menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:Addcontact(&con);break;case DEL:Delcontact(&con);break;case SEARCH:Searchcontact(&con);break;case MODIFY:Modifycontact(&con);break;case SHOW:Showcontact(&con);break;case SORT:SortContact(&con);break;case SAVE:SaveContact(&con);break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("输入错误,请重新输入:>\n");break;}} while (input);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;
}

既然公用一块空间那么(小端)

这个代码运行结果如何呢?

我们发现将i的第4个字节的内容修改为55了(其实是改的低地址处的数据)

同样大端下会打印55223344; 

利用联合体写一个函数判断机器为大端还是小端

int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是⼩端,返回0是⼤端 
}

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

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

相关文章

【Linux 驱动基础】IMX6ULL LED基础驱动

本机使用的是正点原子的IMX6ULL开发板 # 前置知识 IMX6ULL GPIO控制框图&#xff1a; GPIO控制代码大概分为几个流程&#xff1a;开启时钟、设置IO复用、设置IO属性、配置IO方向、设置IO输出电平&#xff0c;下面以IMX6ULL为例&#xff0c; 1. 开启时钟 参考资料&#xff1a…

C 语言的关键字 static 和 C++ 的关键字 static 有什么区别 / C++中,a和a有什么区别?

一、C 语言的关键字 static 和 C 的关键字 static 有什么区别 C语言和C中的关键字static在用法和语义上有一些相似之处&#xff0c;但也存在一些细微的差别。 在C语言中&#xff0c;static关键字主要用于以下三个方面&#xff1a; 修饰全局变量或函数&#xff1a;使用static…

深入理解 Docker 镜像

1. Docker 镜像的底层原理 1.1 分层的镜像 以我们的pull 命令为例&#xff0c;在下载的过程中我们可以看到docker的镜像好像是一层一层的在下载。 1.2 UnionFS(联合文件系统) 联合文件系统是一种分层、轻量级并且高性能的文件系统&#xff0c;它支持对文件系统的修改作为一次…

自学python指导教程

要系统地自学Python&#xff0c;可以按照以下步骤进行&#xff1a; 学习基础知识&#xff1a; 从Python的基础语法开始学习&#xff0c;如变量、数据类型、运算符等。理解Python中的控制流程&#xff0c;如条件语句和循环结构。学习函数的定义和使用。了解Python中常用的数据结…

MPI4.1文档翻译(持续更新)

本博客参考官方文档进行介绍&#xff0c;全网仅此一家进行中文翻译&#xff0c;走过路过不要错过。 官方网址&#xff1a;https://www.mpi-forum.org/ 参考文档&#xff1a;https://www.mpi-forum.org/docs/mpi-4.1/mpi41-report.pdf 引用官方4.1文档方法&#xff1a; manu…

2024最新华为OD机试试题库全 -【局域网中的服务器个数】- C卷

1. 🌈题目详情 1.1 ⚠️题目 在一个机房中,服务器的位置标识在 n*m 的整数矩阵网格中,1 表示单元格上有服务器,0 表示没有。如果两台服务器位于同一行或者同一列中紧邻的位置,则认为它们之间可以组成一个局域网。 请你统计机房中最大的局域网包含的服务器个数。 1.2 …

linux下使用迅雷的完美办法(网络版免费),其他下载工具

迅雷有自家服务器的支持&#xff0c;因此&#xff0c;其他下载器&#xff0c;可能难以匹敌 &#xff1f; linux下使用迅雷的完美办法&#xff08;免费&#xff09; https://blog.csdn.net/lqrensn/article/details/8853949 网络版 Linux下安装并使用迅雷 https://www.lxlin…

牛客题霸-SQL进阶篇(刷题记录一)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 由于涉及到的数据库表较多&#xff0c;因此本文不再展示&#xff0c;只提供 MySQL 代码与示例输出。 部分题目因…

化工企业能源在线监测管理系统,智能节能助力生产

化工企业能源消耗量极大&#xff0c;其节能的空间也相对较大&#xff0c;所以需要控制能耗强度&#xff0c;保持更高的能源利用率。 化工企业能源消耗现状 1、能源管理方面 计量能源消耗时&#xff0c;计量器具存在问题&#xff0c;未能对能耗情况实施完全计量&#xff0c;有…

P - Beat

题目分析 1.看数据范围&#xff0c;大概知道dfs能做 2.自0问题开始查找&#xff0c;确保之后每次查找到的问题的困难度均大于上一次 3.遍历所有情况再记录cnt即可 代码 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring&…

使用easyexcel生成动态头,实时生成头写入,加对应的列

测试类 参考链接&#xff1a;动态头&#xff0c;实时生成头写入 package org.springblade.modules.api.controller;import com.alibaba.excel.EasyExcel; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import c…

蓝桥集训之矩形牛棚

蓝桥集训之矩形牛棚 核心思想&#xff1a;单调队列 模板&#xff1a;Acwing.131.直方图矩形面积首先遍历所有下界 然后确定以该下界为底的直方图 求最大矩形 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 30…

【13】vue2和vue3对比

vite: https://github.com/vitejs/vite 面试题:谈谈你对 vite 的理解,最好对比 webpack 说明 webpack 原理图 vite 原理图 面试题答案: webpack 会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。 而 vite 是直接启动开发服务器,请求哪个模块再对该模块进行实…

30-2 越权漏洞

一、定义: 攻击者利用业务的设计缺陷&#xff0c;获取敏感信息或破坏业务完整性。本质是程序逻辑输入管控不严&#xff0c;未对用户数据进行严格把控&#xff0c;导致程序不能正常处理或处理错误。常见于登录注册、密码找回、信息查看、交易支付等场景。 二、类型: 未授权访…

常见的密码的分类和用途场景原理

一、按用途和管理分类 核心密码&#xff1a; 使用场景&#xff1a;专门用于保护国家最高等级的绝密信息&#xff0c;常见于政府、军队、外交等领域的重要通信及数据加密。特点&#xff1a;极高安全性&#xff0c;由国家密码管理部门统一严格管理&#xff0c;具体算法和密钥严格…

【C语言进阶篇】动态内存管理(一)

个人主页&#xff1a; 倔强的石头的博客 系列专栏 &#xff1a;C语言指南 C语言刷题系列 待补充完善

Linux的一些基本指令

​​​​​​​ 目录 前言&#xff1a; 1.以指令的形式登录 2.ls指令 语法&#xff1a; 功能&#xff1a; 常用选项&#xff1a; 3.pwd指令 4.cd指令 4.1 绝对路径与相对路径 4.2 cd .与cd ..&#xff08;注意cd后先空格&#xff0c;然后两个点是连一起的&#xff0…

华为od真题--2023C卷-地图寻宝华为OD真题题解

小华地图寻宝 题目描述 小华按照地图去寻宝&#xff0c;地图上被划分成m行和n列的方格&#xff0c;横纵坐标范围分别是[0,n-1]和[0,m-1]。在横坐标和纵坐标的数位之和不大于k的方格中存在黄金(每个方格中仅存在一克黄金)&#xff0c;但横坐标和纵坐标之和大于k的方格存在危险不…

编译执行篇

文章目录 11.1 compile()11.2 eval()11.3 exec()11.4 repr() 11.1 compile() 在Python中&#xff0c;compile()是一个内置函数&#xff0c;用于将字符串编译成字节码或AST&#xff08;抽象语法树&#xff09;对象&#xff0c;以便稍后被exec()或eval()函数执行。这对于执行动态…

2024最新华为OD机试试题库全 -【加密算法】- C卷

1. 🌈题目详情 1.1 ⚠️题目 有一种特殊的加密算法,明文为一段数字串,经过密码本查找转换,生成另一段密文数字串。 规则如下: 明文为一段数字串由 0~9 组成 密码本为数字 0~9 组成的二维数组 需要按明文串的数字顺序在密码本里找到同样的数字串,密码本里的数字串是…