【C语言】结构体与位段

一、前言

  • 我们之前学习过定义一个整型类型的变量又或者定义一个浮点型类型的变量...,这些变量可以描述一个整数又或者描述一个小数...,可无论是整数还是小数...,它们也只是简单对象。
  • 如果我们想要描述像一本书,一个人这种复杂对象,用我们之前学习过的类型去描述是完全不够的。一本书包含着很多信息,如书名、价钱、作者、出版时期...。
  • 我们会发现书的其中一个信息的表示我们是学过的,我们也能将其描述出来,如书名啊,作者啊,可以用字符数组,价钱啊,可以用整型...。
  • C语言为我们提供了一种自定义类型结构体,并我们提供了一个声明结构体类型的关键字:struct。

二、如何正确使用结构体?

1.结构体的使用(声明+创建变量+初始化)
  • 小结:创建变量的同时,给成员 ’赋值‘ 的同时,才叫初始化,且可以对全部成员进行’赋值‘;而赋值不可以同时操作结构体的全部成员。
2.匿名结构体
  • 匿名结构体:省去结构体标签的结构体类型叫做匿名结构体
  • 小结:由上面两张代码截图可知,匿名结构体若不被关键字typedef重定义,则只能使用一次(在声明的同时,也进行变量的创建)。
3.结构体自引用
  • 在声明结构体类型时候,包含一个类型为自身的成员,可不可以?
  • 下面我将拿将对上面的People类型的结构体,增加一个成员,让它用来描述伴侣;
  • 第一个代码例子,类型于我们平常所说的无限套娃——结构体包含结构体,而这种做法,导致的是结构体的内存无限大,无法计算结构体的内存,所以这点,C语言是明令禁止的。
  • 第二个代码例子,我用一个结构体指针,若有伴侣了,我让它指向下一个结构体的地址,若无伴侣,则就填NULL;而指针类型的大小只与平台有关,64位平台8个字节,32位平台4个字节。
  • 所以第二代码例子,则是正确的自引用方式——包含自身结构体的指针。
4.结构体的两个操作符
  • 那我们又该如何逐一去访问该结构体的成员呢?其实C语言为我们提供了两个操作符(.)/(->);
  • 当我们知道了结构体的变量的时候,用操作符(.)
  • 当我们知道了指针结构体地址的指针变量的时候,用操作符(->)
  • 小结:(*xcf.girl).name   <----->  xcf.girl->name

三、结构体的内存对齐

1.什么是内存对齐?
  • 结构体占内存中占据的字节并非是简单的内存成员类型大小的标量和,而是存在内存对齐这一规则。
  • 1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处;
  • 2.其余的成员对齐到,(某个数字)对齐数,的整数倍处;
  • 对⻬数 = 编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值
  • VS默认对齐数为8;
  • Linux中gcc没有默认对齐数,对齐数就是成员自身的类型大小。
  • 3.若存在嵌套结构体的情况,则结构体成员对齐到,自己成员中最大对齐数的,整数倍处;
  • 4.结构体最终内存的大小,是结构体中最大对齐数的整数倍。
  • 结构体中每一个成员都有对应的对齐数,对齐数最大的则为最大对齐数。
2.为什么存在内存对齐?
  • 平台原因(移植原因):
  • 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因:
  • 数据结构(尤其是栈)应该尽可能地在⾃然边界上对⻬。原因在于,为了访问未对⻬的内存,处理器需要作两次内存访问;⽽对⻬的内存访问仅需要⼀次访问。假设⼀个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数,那么就可以⽤⼀个内存操作来读或者写值了。否则,我们可能需要执⾏两次内存访问,因为对象可能被分放在两个8字节内存块中。
  • 小结:内存对齐是牺牲时间换空间的一种做法
3.修改默认对齐数

四、位段

1.位段的概念
  • 当我们学习完结构体后,就不得不了解下位段这一概念,何为位段?
  • 结构体的声明与位段的声明是相似的,换而言之,位段的实现是建立在结构体的概念上面的。
  • 位段与结构体有两点不同:
  • 位段的成员类型只能是整型;(如int,unsigned int,signed int,short,char等);
  • 位段的成员变量后面加上冒号与数字;(是位段与结构体最主要的区别),其中数字代表该变量在内存中所占据多少比特位。
  • 注:位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。
  • 下面代码就是位段的声明举例,至于创建变量和初始化,和结构体一样
2.位段的内存分配
  • 位段一次性开辟内存的大小是按照所需要,开辟char、short、int大小的字节。
  • 位段最终的内存大小,是最大对齐数的整数倍。
  • 不同平台上,位段的内存分配不同,也就导致了相同位段,不同平台的内存大小不同;
3.位段的跨平台问题
  • 不同平台上,int是无符号整型,还是有符号整型是不确定的——VS上面int是由符号整型
  • 一次性开辟的内存空间是从左向右使用(从低地址->高地址),还是从右向左使用是不确定的——VS上面内存空间的使用是从右向左的;
  • 剩下的内存空间不够下一个位段成员的填充,是否浪费是不确定的——VS上面是选择浪费的
  • 下面是三个例子:(是我查找各种资源+咨询+寻找典型的例子,才得到的结果)
4.位段的注意事项
  • 由上面三组代码的三个内存布局的研究,我们可以知道,位段成员的起始位置不是某个字节的地址,而是莫个bite位的地址。
  • 我们在指针篇了解到地址是内存单元的编号,也就是一个字节的地址,而一个bite位是没有地址的。
  • 所以位段的成员是没有地址的,也就不能&操作,进行scanf输入。所以我们只能通过临时变量去赋值给位段成员。

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

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

相关文章

【算法与数据结构】深入二叉树实现超详解

文章目录 &#x1f4dd;前言&#x1f320; 接口函数✏️ 实现函数&#x1f309;创建树的新节点&#x1f320;通过前序遍历的数组构建二叉树&#x1f309;包装通过前序遍历的数组构建二叉树&#x1f320;二叉树的销毁&#x1f320;层次遍历&#x1f320;第一种实现&#xff1a;不…

Android: Gradle 命令

一、查看整个项目依赖传递关系 x.x.x (*) 该依赖已经有了&#xff0c;将不再重复依赖。x.x.x -> x.x.x 该依赖的版本被箭头所指的版本代替。x.x.x -> x.x.x(*) 该依赖的版本被箭头所指的版本代替&#xff0c;并且该依赖已经有了&#xff0c;不再重复依赖。 1. gradlew ap…

002 高并发内存池_定长内存池设计

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;高并发内存池 &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 前言一、设计整体框架二、New操作&#xff08;申请空间&#xff09;三、Delete操作&#xff08;用自由链…

奇舞周刊第523期:来自 rust 生态的强烈冲击?谈谈 Leptos 在语法设计上的精妙之处...

奇舞推荐 ■ ■ ■ 来自 rust 生态的强烈冲击&#xff1f;谈谈 Leptos 在语法设计上的精妙之处 过去很长一段时间&#xff0c;前端框架们都在往响应式的方向发展。同时又由于 React hooks 的深远影响&#xff0c;函数式 响应式成为了不少前端心中最理想的前端框架模样。Solid …

设计模式-初步认识

目录 &#x1f6fb;1.什么是设计模式 &#x1f69a;2.设计模式的优点 &#x1f68d;3.设计模式6大原则 &#x1f6f4;4.设计模式类型 1.什么是设计模式 设计模式代表了最佳的实践&#xff0c;通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开…

Yocto学习笔记1-下载与首次编译

Yocto学习笔记1-下载与首次编译 1、基础环境介绍2、注意点3、安装依赖3.1 yocto常规系统构建所需依赖库&#xff08;较全&#xff09;3.2 龙芯适配时的最小依赖库&#xff08;最小&#xff09; 4、下载4.1 通过git克隆4.2 查看所有远程分支4.3 签出一个长期支持的稳定版本4.4 查…

从边缘设备丰富你的 Elasticsearch 文档

作者&#xff1a;David Pilato 我们在之前的文章中已经了解了如何丰富 Elasticsearch 本身和 Logstash 中的数据。 但如果我们可以从边缘设备中做到这一点呢&#xff1f; 这将减少 Elasticsearch 要做的工作。 让我们看看如何从具有代理处理器的 Elastic 代理中执行此操作。 E…

Redis如何删除大key

参考阿里云Redis规范 查找大key&#xff1a; redis-cli --bigkeys 1、String类型&#xff1a; Redis 4.0及以后版本提供了UNLINK命令&#xff0c;该命令与DEL命令类似&#xff0c;但它会在后台异步删除key&#xff0c;不会阻塞当前客户端&#xff0c;也不会阻塞Redis服务器的…

【漏洞复现】WordPress Plugin NotificationX 存在sql注入CVE-2024-1698

漏洞描述 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress Plugin NotificationX 存在安全漏洞,该漏洞源于对用户提供的…

MySQL:表的操作

文章目录 创建表查看表结构修改表删除表 前面对于库的操作有了认识后&#xff0c;下面进行表的操作 创建表 以下图为例 创建表其实和定义结构体有点类似&#xff0c;总的来说就是先定义列名&#xff0c;然后后面跟着是列的数据类型&#xff0c;之后在定义结束后可以带上对应的…

【数据挖掘】实验4:数据探索

实验4&#xff1a;数据探索 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握数据探索&#xff0c;学习数据质量分类、数据特征分析和R语言的主要数据探索函数。 二&#xff1a;实验内容 1&#xff1a;数据质量分析 2&#xff1a;统计量分析 3&#xff1a;贡献度分析…

Redis常见数据类型(1)

Redis提供了5种数据结构, 理解每种数据类型的特点对于Redis开发运维非常重要, 同时掌握每种数据类型的常见命令, 会在使用Redis的时候做到游刃有余. 内容如下: 预备知识: 几个全局命令, 数据结构和内部编码, 单线程机制解析. 5种数据类型的特点, 命令使用, 应用场景示例. 键遍历…

uniapp微信小程序_购物车_下单页面

先说下整体逻辑以方便总体理解 1、首先画出下单页面 2、此次画出结算价格页面 3、怎么点击下完单变成结算页面&#xff1f;其实就是把下单页面的信息传递给结算页面就行 问题难点&#xff1f; 点击加号的时候把物品加入一个数组传到下单页面&#xff0c;但是点击的时候不能…

2024-03-24 需求分析-智能问答系统-调研

一. 需求列表 基于本地知识库的问答系统对接外围系统 数字人语音识别二. 待调研的公司 2.1 音视贝 AI智能外呼_大模型智能客服系统_大模型知识库系统_杭州音视贝 (yinshibei.com) 2.2 得助智能 智能AI客服机器人-智能电话机器人客服-电话电销机器人-得助智能 (51ima.com) 2…

LabVIEW比例流量阀自动测试系统

LabVIEW比例流量阀自动测试系统 开发了一套基于LabVIEW编程和PLC控制的比例流量阀自动测试系统。通过引入改进的FCMAC算法至测试回路的压力控制系统&#xff0c;有效提升了压力控制效果&#xff0c;展现了系统的设计理念和实现方法。 项目背景&#xff1a; 比例流量阀在液压…

使用 chezmoi vscode, 管理你的 dotfiles

什么是 dotfiles In Unix-like operating systems, any file or folder that starts with a dot character (for example, /home/user/.config), commonly called a dot file or dotfile. 任何以 . 开头去命名的文件或者目录都可以称为 dotfile, 在 Unix-like 系统一般用的比较…

Mysql数据库深入理解

目录 一、什么是数据库 二、Mysql基本架构图 1.Mysql客户端/服务器架构 2.客户端与服务器的连接过程 3.服务器处理客户端请求 4.一条查询SQL执行顺序 4.1连接器 4.2查询缓存 4.3解析器 4.4执行器 4.4.1预处理阶段 4.4.2优化阶段 4.4.3执行阶段 5.一条记录如何存…

外包干了4年,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

【十六】MySQL数据库设计篇

MySQL数据库设计篇 概述 做服务端开发离不开数据库设计&#xff0c;虽然说服务端技术一直在革新&#xff0c;但是MySQL一直都是我们首选使用的关系型数据库。服务端开发一直以来都是采用数据驱动研发的思想&#xff0c;可见数据库设计是非常重要的&#xff0c;数据库设计的好坏…

01.重新认识文件(Linux基本概念)

知识引入&#xff1a; 我们经常使用word或者wps写的论文、作业等都是文件&#xff0c;而我们这样对文件的认识也比较片面。我们是否思考过&#xff0c;如果文件里面没有写东西&#xff0c;那么计算机会不会保存呢&#xff1f;答案是&#xff0c;肯定会的。因为我们每次建的空文…