(超详解)--->自定义类型(结构体,枚举,联合)

news2025/1/10 21:13:17

目录

本章学习重点:

        1:结构体类型的声明与变量的定义

        2:如何求解结构体的大小(结构体的内存对齐)

        3:结构体传参,结构体实现位段

        4:枚举类型的定义和优点

        5:联合的定义与特点及大小的计算


1:结构体类型的声明与变量的定义

        结构:结构是一些集合,这些值指的是成员变量。结构体的成员变量可以是不同类型的变量。

        结构的声明-->

        

 tag:是可以自己起名字。

member_list:结构体的成员变量的类型声明。

variable_list:结构体变量可以在此定义。

如果将tag去掉的话,那么此结构体是一个特殊的声明也称结构体的不完全声明,定义变量的时候只能在variable-list此处定义。‘

struct tag才叫结构体的定义类型。

 如果定义两个匿名结构体类型的话,尽管他们的成员变量相同但是编译器会认为他们的类型不同的。所以此时如果用结构体指针指向另外一个结构体是非法的 。

  结构体的自引用:即结构体里面包含指向自身结构的指针。

        不能是结构体的原因:假设是结构体里面包含结构体,则会形成无限套娃的形式sizeof(结构体)的大小就不能够计算出来了。

结构体变量的定义与初始化

结构体变量的定义可以分为两种情况下定义:

                1:在结构体声明的时候定义变量与进行初始化.s1,s2

        2:在用类型加变量名定义的时候初始化。s3,s

      2:求解结构体的大小(结构体的内存对齐)

        首先我们来了解结构体的对齐规则:

                1:结构体的第一个成员在结构体偏移量为0的地址处,即结构体的起始位置开始处。

                2:其他成员变量对齐到某个对齐数的整数倍地址处。

                        对齐数=结构体成员本身的大小与编译器默认的对齐数的较小值

                3:结构体的最终大小最大对齐数(每个成员变量对齐数的最大值)的整数倍

                4:如果包含结构体嵌套,那么嵌套的结构体对齐到自身最大对齐数的整数倍地址处,结构体的整体大小就是所有最大对齐数(含嵌套结构体)的整数倍处。

           练习:

        

struct S1
{
 char c1;
 int i;
 char c2;
};

printf("%d\n", sizeof(struct S1));

     图解:

解释:首先我们先将c1变量放在偏移量为0的地址处,大小为1个字节。

        i的大小为4个字节而vs默认对齐数为8,所以对齐数为4,所以我们的结构体就会浪费3个字节的空间使i偏移到地址为4处开始

        c2变变量自身大小为1,对齐数为1所以c2变量直接在i后1个字节的空间就行。

        现在的大小为9个字节,根据第三条规则,结构体的大小为最大对齐数的整数倍,而此处大小为4,所以还要浪费三个字节的空间,所以最终答案为12. 

为啥会存在结构体内存对齐呢?

        平台原因:不是所有的硬件平台都够访问任意地址上的任意处的数据,如果访问的话则会抛出硬件异常。

        性能原因:数据结构(尤其是栈),如果内存未对齐那么我们的处理器需要两次内存访问,而对齐了的话则只需要一次访问就行

    总的来说:结构体内存对齐就是拿空间来换时间

为了即提高空间的效率与时间的效率,避免浪费太多的空间,我们可能会使成员变量小的尽可能放在一起  

我们可以使用 #pragma pack()   来改变平台默认对齐数

3:结构体传参与位段

结构体传参的时候可以传结构体,也可以传地址,那么我们应该选哪个呢?

        一般我们都会选择传地址,这是因为形式参数会在内存中进行压栈等操作,会浪费一定的时间与空间,如果结构体足够大,那么形式参数所需要的时间与空间的消耗更大,导致性能的下降。

        结论:结构体传参的时候传地址

位段:

        其实位段也是在结构体的基础上进行的操作,只是说它的语法不完全相同如:

        

struct s
{
    int a:4;
    int b:5;
    int c:6;
    //位段的成员名后边有一个冒号和一个数字
    //位段成员的类型必须为整形家族的
    
};

        这些后面的数字单位都是字节

位段开辟空间的时候一般是按照4个字节的空间开辟或者是按照1个字节的空间开辟

当既有整形又有字符型的时候一般都是按照整形进行开辟空间的

4:枚举的定义与优点

        定义:涉及一个关键字enum,生活中有些事物是可以一一列举出来的,枚举就是将所有可能一一列举出来的,比如说一周有多少天,三原色,性别...

        

在enum{}当中的成员,又可以叫做枚举常量,且他们的值是依次递增1的,当然也可以给他们赋值。其中enum sex称作枚举类型

 优点:

        与#define相比,   1.枚举可以增加代码的可读性和可维护性

                                      2.与#define相比枚举定义的常量有类型检查,更加严谨

                                       3.便于调试

                                       4.使用方便1次可以定义多个常量

只能拿枚举常量给枚举变量赋值。其他类型的常量会error

5:共用体的定义与特点及大小的计算

共用体:一般用union来定义比如:

union Un

{
 char c;
 int i;
};

特点:是共用体共用同一块内存空间,也就是说共用体的大小最小为成员变量类型的最大值

共用体的计算:

联合的大小至少是最大成员的大小。

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

                        感谢大家的观看!

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

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

相关文章

Kind | Kubernetes in Docker 把k8s装进docker!

有点像杰克船长的黑珍珠 目录 零、说明 一、安装 安装 Docker 安装 kubectl 安装 kind 二、创建/切换/删除集群 创建 切换 删除 将镜像加载到 kind 群集中 零、说明 官网:kind Kind: Kubernetes in Docker 的简称。kind 是一个使用 Docker 容…

【技能实训】DMS数据挖掘项目-Day09

文章目录 任务9【任务9.1.1】升级DataBase类为可序列化的类,以便在文件保存或网络中传递【任务9.1.2】升级LogRec类为可序列化的类,以便在文件保存或网络中传递【任务9.1.3】升级MatchedLogRec类为可序列化的类,以便在文件保存或网络中传递【…

java通过正则表达式提取信息

java通过正则表达式提取信息 工具类如下 package com.datafactory.util;import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component;import java.util.regex.Matcher; import java.util.regex.Pattern;Component Slf4j public class RegexUtils {/…

“简单易懂的排序:深入了解直接选择排序“

文章目录 🔍 选择排序的原理与过程📈 选择排序的优缺点👉 代码实现 🔍 选择排序的原理与过程 本文我们直接说一个优化过的直接选择排序。其思路大同小异. 选择排序的思路很简单 每次从待排序的数据中选择一个最小和最大的元素&a…

记一次rabbitmq消息发送成功,消费丢失问题

记一次rabbitmq消息发送成功,消费丢失问题 背景 测试数据归档,偶现数据未归档 排查 idea线上调试,log日志,数据库消息发送记录,代码分块重复执行看哪块出的问题,结果均无问题,最后使用rabbi…

网关选型对比

网关选型 网关简介 网关是将一个网络与另一个网络进行相互连通,提供特定应用的网络间设备,应用网关必须能实现相应的应用协议。应用网关可以看做是运行于要求特定业务的客户机与提供所需业务的服务器之间的中间过程。应用网关在这类过程中,从…

MySQL练习题(6)

创建两个表插入数据 CREATE DATABASE beifen;use beifen;CREATE TABLE books(bk_id INT NOT NULL PRIMARY KEY,bk_title VARCHAR(50) NOT NULL,copyright YEAR NOT NULL);INSERT INTO booksVALUES (11078, Learning MySQL, 2010),(11033, Study Html, 2011),(11035, How to u…

Linux—实操篇:组管理和权限管理

目录 1、Linux组基本介绍 2、文件/目录 所有者 2.1、查看文件所有者 2.1、修改文件的所有者 3、组的创建 4、文件/ 目录所在组 4.1、查看文件/目录所在组 4.2、修改文件/ 目录所在组 5、其他组 6、改变用户所在组 7、权限基本介绍 8、rwx权限详解 8.1、rwx作用到文…

除了单测、写main方法,还有其他验证方式吗?试试Java JShell吧!

文章首发地址 JShell 概述 Java JShell 是 JDK 9 中引入的一个交互式命令行工具,可以方便地测试 Java 代码片段和进行试验性的 Java 编程。JShell 可以帮助开发人员轻松地创建和测试 Java 代码,而无需编写和运行完整的应用程序或测试用例。以下是 JShe…

了解刚性、惯量、响应时间及伺服增益之间的关系,提高系统的性能和稳定性!

在伺服系统选型及调试中,刚性、惯量、响应时间及伺服增益调整之间的关系错综复杂,这些因素在控制系统中相互影响,对于系统的稳定性和性能至关重要。但在实践中如何调整取值比较合理,这些就算是工程师都会经常感到困惑。所以了解它…

Django 分布式路由

简介: Django中,主路由配置文件(urls.py)可以不处理用户具体路由,主路由的配置文件可以配置成做请求的分发(分布式请求处理,分发到子路由而不是具体的视图函数)。具体的请求可以由各自的应用来处理。 步骤…

stm32(SPI读写W25Q18)

SPI 是什么? SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总 线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PC…

【Nginx】rewrite简单使用

前言 没有对正式的rewrite进行了解,为了能快速了解它是干嘛怎么用,找了一些有例子的博客进行简单学习了一下;由于每次看的间隔有点大,老忘记,这回专门写个超级快速理解的例子。 PS:下面的解释可能会不太对…

Serverless和EDA是绝配,亚马逊云科技CTO Werner表示需要用开放心态来重新审视架构

前一段有个很火的博客,讲的是一家全球流媒体企业的监测系统从Serverless微服务改成了单体,成本居然降低了90%!这一下子可在网上炸锅了,特别是一些看不惯微服务的、单体应用的拥趸,更是坐不住了。但这并不像吃瓜群众看到…

ret2syscall-执行系统调用

题目 checksec一下: 32位程序,没有canary、PIE,开了NX,放入IDA看一下: 有gets,可以溢出,不过没有system函数,也不能执行shellcode,查看字符发现有/bin/sh,那就…

消息中间件系列 - RocketMQ

前言 本内容仅用于个人学习笔记,如有侵扰,联系删除 【尚硅谷】RocketMQ教程丨深度掌握MQ消息中间件_哔哩哔哩_bilibili 第一章 RocketMQ概述 一、MQ概述 1 、MQ简介 MQ,Message Queue,是一种提供消息队列服务的中间件&#…

SpringBoot(七)Filter的使用

思考一个问题,服务端对于客户端的请求,真的应该照单全收吗?不是的。比如拿我们之前实现的用户注册功能来看,如果用户的昵称带了一些不友好的字母或汉字,你是给他过滤掉呢还是让他注册呢?毫无疑问&#xff0…

Zint-条码生成软件-命令行调用-一维条码和二维条码

文章目录 1.Zint简介2.术语3.命令行3.1.输入数据3.2.直接输出3.3.选择条码类型3.4.调整高度3.5.调整空白3.6.添加边界条和框3.7.颜色设置3.8.旋转3.9.调整图像尺寸 4.界面5.总结 1.Zint简介 Zint项目旨在提供一个完整的跨平台开源条形码生成解决方案。该软件包目前包括一个基于…

零拷贝是如何实现的

零拷贝是如何实现的 零拷贝(Zero-copy)是一种优化技术,用于在数据传输过程中减少数据的拷贝次数,从而提高数据传输的效率和性能。传统的数据传输涉及多次内存拷贝操作,而零拷贝通过减少或避免这些拷贝操作来实现性能优…

HDC.Cloud 2023|邂逅AI,华为云CodeArts铸就研发效能10倍提升

2023年7月7日-9日,华为开发者大会2023(Cloud)在东莞松山湖隆重举行。期间,华为云主办了以“AI‘邂逅’一站式软件开发,CodeArts以10倍效能“绘”企业应用远景”为主题的分论坛。 华为云PaaS服务产品部副部长汪维敏携一…