【C语言】结构体与位段

2024-03-24 15:52
文章标签 语言 结构 位段

本文主要是介绍【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输入。所以我们只能通过临时变量去赋值给位段成员。

这篇关于【C语言】结构体与位段的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842063

相关文章

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

Go语言中最便捷的http请求包resty的使用详解

《Go语言中最便捷的http请求包resty的使用详解》go语言虽然自身就有net/http包,但是说实话用起来没那么好用,resty包是go语言中一个非常受欢迎的http请求处理包,下面我们一起来学... 目录安装一、一个简单的get二、带查询参数三、设置请求头、body四、设置表单数据五、处理响应六、超

C语言中的浮点数存储详解

《C语言中的浮点数存储详解》:本文主要介绍C语言中的浮点数存储详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、首先明确一个概念2、接下来,讲解C语言中浮点型数存储的规则2.1、可以将上述公式分为两部分来看2.2、问:十进制小数0.5该如何存储?2.3 浮点

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、