自定义类型——结构体、枚举和联合

自定义类型——结构体、枚举和联合

  • 结构体
    • 结构体的声明
    • 匿名结构体
    • 结构体的自引用
    • 结构体的初始化
    • 结构体的内存对齐
    • 修改默认对齐数
    • 结构体传参
  • 位段
  • 枚举
  • 联合

结构体

  • 结构是一些值的集合,这些值被称为成员变量,结构的每个成员可以是不同类型的变量。

数组是一些值的结合,类型是相同的

结构体的声明

	struct tag{member_list;}variable_list;//全局变量
  • 这里通过前面的列表创建的变量是全局变量
	typedef struct tag{member_list;}tag;//相当于struct tag
  • typedef可以将复杂的类型简化

匿名结构体

	struct{member_list;}variavle_list;//必须存在
  • 匿名结构体类型,如果没有对结构体类型重命名,只能使用一次

结构体的自引用

//结构体的自引用
struct stu
{int age;struct stu* next;
};
typedef struct stu
{int age;struct stu* next;
}stu;

结构体的初始化

//结构体的初始化#include<stdio.h>
struct student
{char name[10];unsigned int age;char sex[5];
};int main(void)
{//初始化struct student n1 = { "张三",21,"男"};//打印printf("%s %u %s", n1.name, n1.age, n1.sex);return 0;
}

运行截图
运行截图

结构体的内存对齐

//结构体的内存对齐
#include<stdio.h>
struct eg1
{int i;char j;char k;
};struct eg2
{char x;int y;char z;
};int main(void)
{//打印eg1printf("%zd\n", sizeof(struct eg1));//8//打印eg2printf("%zd\n", sizeof(struct eg2));//12return 0;
}
  • 结构体对齐规则

1.结构体的第一个成员,对齐到结构体在内存中存放位置的0偏移处
2.从第二个成员开始,每个成员都要对齐到(一个对齐数)的整数倍处

对齐数:
结构体成员自身大小和默认对齐数的较小值

在VS中:默认对齐数为8
Linux gcc:没有对齐数,对齐数就是成员自身大小

3.结构总大小为最大对齐数的较小值
4.如果结构体中嵌套了结构体成员,要将嵌套的成员对齐到自己的成员中最大对齐数的整数倍处
5.结构体的总大小必须是最大对齐数的整数倍,这里的最大对齐数是:包含嵌套结构体成员中的对齐数的所以对齐数中的最大值

  • 结构体内存对齐的原因

1.平台原因:
不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在地址处取某些特定类型的数据,否则会抛出硬件异常

2.性能原因:
数据结构(尤其是栈)应该尽可能的在自然边界上对齐,原因在于,为了访问来对齐的内存,处理器需要作俩次内存访问,而对齐的内存仅需要一次访问

总结:
结构体的内存对齐是拿空间来换取时间的做法(满足对齐,节省空间:让占用空间小的成员尽量集中在一起)

修改默认对齐数

#pragma pack()可以设置默认对齐数

//修改默认对齐数
#include<stdio.h>
//修改默认对齐数为2
#pragma pack(2)struct eg1
{char s1;int s2;
};//恢复默认对齐数
#pragma pack()struct eg2
{char s1;int s2;
};int main(void)
{//打印eg1printf("%zd\n",sizeof(struct eg1));//6//打印eg2printf("%zd\n", sizeof(struct eg2));//8return 0;
}

总结:
结构在对齐方式不合适的时候,可以自己更改默认对齐数

结构体传参

//结构体传参
#include<stdio.h>struct eg
{int arr[100];char ch[20];
}s1 = { {1,2,3,4,5} ,"abcdef"};
//结构体传参
void print1(struct eg s1)
{printf("%s\n",s1.ch);
}
//结构体地址传参
void print2(struct eg* ps)
{printf("%s\n",ps->ch);
}
int main(void)
{//结构体传参print1(s1);//结构体地址传参print2(&s1);return 0;
}

运行截图:
截图

  • 总结:结构体传参的时候,要传结构体的地址
  • 原因在于,函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销

  • 如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以导致性能下降

位段

  • 位段的声明和结构体的声明基本相似,但也存在俩点不同:

1.位段的成员必须为int,unsigned int或者 signed int
2.位段的成员名后面有一个冒号和一个数字

//位段
#include<stdio.h>
struct eg
{int _a : 2;int _b : 5;int _c : 10;int _d : 20;
};int main(void)
{printf("%zd",sizeof(struct eg));return 0;
}

运行截图:
在这里插入图片描述

  • 位段:二进制位,可以节省空间

位段的内存分配
1.位段的成员可以是int,unsigned int,signed int或者是char (属于整数家族)类型
2.位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的
3.位段涉及很多不确定因素,位段时不跨平台的,注重可移植的程序应该避免使用位段

位段的跨平台问题
1.int位段被当成有符号数还是无符号数是不确定的
2.位段中最大位的数目不能确定(16位机器最大16,32位机器最大32,写成27时可能在16位机器上出现问题)
3.位段中的成员在内存中从左到右分配,而且从右向左标准尚未定义
4.当一个结构包含俩个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的

总结:跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在

枚举

  • 枚举:即一 一列举
//枚举
enum Day
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};enum Color
{Green,Blue,Red,Orange
};

enum Day和enum color都是枚举类型,{ }中的内容是枚举类型的可能取值,也叫枚举常量。这些枚举常量都是存在取值的,默认是从0开始,一次低递加1

  • 也可以在定义的时候赋值
enum Day
{Mon = 1,Tues = 2,Wed = 3,Thur = 4,Fri = 5,Sat = 6,Sun = 7
};

枚举的优点:
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较,枚举由类型检查,更加严谨
3.防止了命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个变量

联合

  • 联合同样也是一种自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共同体)
//联合
union eg
{char i;int j;
};
  • 特点:

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)

  • 联合大小的计算:

1.联合的大小至少是最大成员的大小
2.当最大成员大小不是最大对齐数的整数的时候,就有对齐到最大对齐数的整数倍

//联合
#include<stdio.h>
union eg
{char i;int j;
};
int main(void)
{union eg s;printf("%p\n", &s.i);printf("%p\n", &s.j);return 0;
}

在这里插入图片描述

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

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

相关文章

【面试经典题】环形链表

个人主页&#xff1a;一代… 个人专栏&#xff1a;数据结构 在面试中我们经常会遇到有关链表的相关题目&#xff0c;面试官通常会对题目给出拓展 下面我就两个leetcode上的一个双指针的题目为例&#xff0c;并对其进行拓展 题目链接&#xff1a;环形链表 题目描述&#xf…

Java抽象类:为何它是你代码架构的基石?

目录 1、抽象类的概念 2、抽象类语法 3、抽象类特性 4、抽象类的作用 5、 完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章专栏&#xff1a;javaSE的修炼之路 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克…

人脸消费给传统食堂带来的变化

消费的技术基础是脸部识别&#xff0c;脸部识别是基于人的容貌特征信息进行认证的生物特征识别技术&#xff0c;其突出的特征是以非接触方式进行识别&#xff0c;避免个人信息的泄露。 面部识别和指纹识别、掌纹识别、视网膜识别、骨骼识别、心率识别等都是人体生物特征识别技术…

【C语言/数据结构】栈:从概念到两种存储结构的实现

目录 一、栈的概念 二、栈的两种实现方式 1.顺序表实现栈 2.链表实现栈 三、栈的顺序存储结构及其实现 1.栈的声明 2.栈的初始化 3.栈的销毁 4.栈的压栈 5.栈的弹栈 6.栈的判空 7.返回栈顶元素 8.返回栈的长度 四、栈的链式存储结构及其实现 1.栈的声明 2.栈的…

【SRC实战】前端脱敏信息泄露

挖个洞先 https://mp.weixin.qq.com/s/xnCQQCAneT21vYH8Q3OCpw “ 以下漏洞均为实验靶场&#xff0c;如有雷同&#xff0c;纯属巧合 ” 01 — 漏洞证明 一、前端脱敏&#xff0c;请求包泄露明文 “ 前端脱敏处理&#xff0c;请求包是否存在泄露&#xff1f; ” 1、获取验…

3.整数运算

系列文章目录 信息的表示和处理 : Information Storage&#xff08;信息存储&#xff09;Integer Representation&#xff08;整数表示&#xff09;Integer Arithmetic&#xff08;整数运算&#xff09;Floating Point&#xff08;浮点数&#xff09; 文章目录 系列文章目录前…

钟表——蓝桥杯十三届2022国赛大学B组真题

问题分析 这个问题的关键有两点&#xff1a;1.怎么计算时针&#xff0c;分针&#xff0c;秒针之间的夹角&#xff0c;2.时针&#xff0c;分针&#xff0c;秒针都是匀速运动的&#xff0c;并非跳跃性的。问题1很好解决看下面的代码就能明白&#xff0c;我们先考虑问题2&#xf…

Springboot+Vue项目-基于Java+MySQL的车辆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Rx(Reactive Extensions)的由来

既然我们已经介绍了响应式编程&#xff0c;现在是时候了解我们的明星了:响应式扩展&#xff0c;通常简称为Rx。微软开发了Reactive扩展库&#xff0c;使其易于处理事件流和数据流。在某种程度上&#xff0c;时变值本身就是一个事件流;每个值更改都是一种类型的事件它会更新依赖…

Vue中使用$t(‘xxx‘)实现中英文切换;

&#xff08;原文链接&#xff09; 介绍 {{$t(key)}} &#xff1a;是VueI18n插件提供的函数&#xff0c;主要用于根据当前语言环境返回对应的翻译文本&#xff0c;以便在页面上显示多语言内容。 key&#xff1a;作为参数传递给函数$t()的字符串&#xff0c;用于指定需要翻译的…

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?

文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字&#xff08;C98&#xff09;3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…

MySQL 通过 systemd 启动时 hang 住了……

mysqld&#xff1a;哥&#xff0c;我起不来了…… 作者&#xff1a;贲绍华&#xff0c;爱可生研发中心工程师&#xff0c;负责项目的需求与维护工作。其他身份&#xff1a;柯基铲屎官。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编…

【Docker学习】重启容器的docker restart

命令&#xff1a; docker container restart 描述&#xff1a; 重启一个或多个容器 用法&#xff1a; docker container restart [OPTIONS] CONTAINER [CONTAINER...] 别名&#xff1a; docker restart(docker的一些命令可以简写&#xff0c;docker restart就等同于docker cont…

SQLZOO:The JOIN operation

数据表&#xff1a;game-gaol-eteam game idmdatestadiumteam1team210018 June 2012National Stadium, WarsawPOLGRE10028 June 2012Stadion Miejski (Wroclaw)RUSCZE100312 June 2012Stadion Miejski (Wroclaw)GRECZE100412 June 2012National Stadium, WarsawPOLRUS... goal …

UE4_照亮环境_不同雾效的动态切换

一、问题及思路&#xff1a; 我们在一个地图上&#xff0c;经常切换不同的区域&#xff0c;不同的区域可能需要不同的色调&#xff0c;例如暖色调的野外或者幽暗的山洞&#xff0c;这两种环境上&#xff0c;雾效的选用肯定不一样&#xff0c;夕阳西下的户外用的就是偏暖的色调&…

【小白的大模型之路】基础篇:Transformer细节

基础篇&#xff1a;Transformer 引言模型基础架构原论文架构图EmbeddingPostional EncodingMulti-Head AttentionLayerNormEncoderDecoder其他 引言 此文作者本身对transformer有一些基础的了解,此处主要用于记录一些关于transformer模型的细节部分用于进一步理解其具体的实现机…

LeetCode_栈和队列相关OJ题目

✨✨所属专栏&#xff1a;LeetCode刷题专栏✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 上一篇&#xff1a;数据结构_栈和队列(Stack & Queue)-CSDN博客 有效的括号 解析: 这里我们用数组实现的栈来解决这个问题&#xff0c;在有了栈的几个基础接口之后&#xff0c;我们运用这…

【Chrome实用命令笔记】

文章目录 Chrome实用命令笔记1、chrome基本介绍2. 打开开发者工具&#xff08;DevTools&#xff09;方法一&#xff1a;快捷键方法二&#xff1a;右键菜单方法三&#xff1a;浏览器设置 2. 开发者工具面板Elements面板Console面板Sources面板Network面板Performance面板Memory面…

(done) Beam search

参考视频1&#xff1a;https://www.bilibili.com/video/BV1Gs421N7S1/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 &#xff08;beam search 视频&#xff09; 参考博客1&#xff1a;https://jasonhhao.github.io/2020/06/19/…

Springboot项目如何创建单元测试

文章目录 目录 文章目录 前言 一、SpringBoot单元测试的使用 1.1 引入依赖 1.2 创建单元测试类 二、Spring Boot使用Mockito进行单元测试 2.1 Mockito中经常使用的注解以及注解的作用 2.2 使用Mockito测试类中的方法 2.3 使用Mockito测试Controller层的方法 2.4 mock…