【C语言】自定义类型:结构体、枚举、联合

news/2024/4/26 6:20:22/文章来源:https://blog.csdn.net/qq_74455045/article/details/128646728

目录

1.结构体

1.1结构体类型

1.2结构体的自引用

1.3结构体的初始化

1.4结构体内存对齐

//对齐

//offsetof  

//修改默认对齐数

1.5结构体传参

 2.位段

2.1位段的内存开辟

2.2位段的内存分配

3.枚举

4.联合(共用体) 

//判断大小端


1.结构体

1.1结构体类型

常见的结构体就不赘述了哈~直接见下图。

匿名结构体:顾名思义,就是没有名字的结构体,在后续进程中不能直接使用,所以要在定义时就创建全局变量。

 

1.2结构体的自引用

小Tips:链表:数据结构——>数据在内存中存储的结构

struct Node
{int date;struct Node* next;//一个节点中包含同类型的下一个节点的地址
};
int main()
{struct Node n1;struct Node n2;n1.next = &n2;//n1中的next存放n2的地址return 0;
}//重命名
typedef struct Node
{int date;struct Node* next;//注意这里的struct不能去掉
}Node;

1.3结构体的初始化

struct P
{int x;int y;
};
struct S
{int num;char ch;struct P p;float d;
};
int main()
{struct P p = { 1,2 };struct S s1 = { 100,'w',{6,8},3.14 };//顺序赋值struct S s2 = { .d = 5.2f,.p.x = 2,.p.y = 3,.ch = 'a',.num = 10 };//乱序赋值printf("%d %c %d %d %f\n", s1.num, s1.ch, s1.p.x, s1.p.y, s1.d);printf("%d %c %d %d %f\n", s2.num, s2.ch, s2.p.x, s2.p.y, s2.d);return 0;
}

1.4结构体内存对齐

结构体对齐规则:(拿空间换时间)

1> 结构体的第一个成员对齐到结构体在内存中存放位置的0偏移处;

2> 从第二个成员开始,每个成员都要对齐到一个对齐数的整数倍处;

(对齐数:结构体成员自身大小和默认对齐数的较小值;默认对齐数:VS环境下(与32位或64位无关)为8,Linux gcc 环境下没有对齐数,对齐数就是结构体成员的自身大小);

修改默认对齐数:#program pack() 

3> 结构体的总大小,必须是所有成员(包含嵌套结构体成员)的对齐数中最大对齐数的整数倍

4> 如果结构体中嵌套了结构体成员,要将嵌套的结构体成员对齐到该结构体中本身成员中最大对齐数的整数倍处;

5> 节省空间:尽量让占用空间小的成员集中在一起

//对齐

struct S1
{char c1;int i;char c2;
};
struct S2
{char c1;char c2;int i;
};
int main()
{printf("%d\n", sizeof(struct S1));//12printf("%d\n", sizeof(struct S2));//8return 0;
}

 

//offsetof  

如果还不信(bushi,可以用 offsetof 来检验:

格式:offsetof (type,member)

功能:计算结构体中某变量相对于首地址的偏移。

头文件:#include<stddef.h>

 

//修改默认对齐数

#pragma pack(1)//修改默认对齐数为1,相当于不对齐
struct S
{char c1;int num;char c2;
};
#pragma pack()//取消修改的对齐数,恢复为默认8
int main()
{printf("%d\n", sizeof(struct S));//6return 0;
}

1.5结构体传参

struct S
{int data[1000];int num;
};
struct S s = { {1,2,3,4}, 1000 };//结构体传参
void print1(struct S s)
{printf("%d\n", s.num);
}//结构体地址传参
void print2(struct S* ps)
{printf("%d\n", ps->num);
}int main()
{print1(s); //传结构体print2(&s); //传地址return 0;
}

以上两种方法,首选print2函数,因为函数传参时,参数需要压栈,时间和空间均有开销。如果传递的结构体对象过大时,参数压栈的系统开销比较大,会导致性能下降。(详见:函数栈帧的创建和销毁)

 2.位段

位:二进制(比特)位

1.位段的成员必须是 int、unsigned int 、signed int 或 char (整形家族);
2.位段的成员名后边有一个冒号和一个数字

3.位段只能在结构体中使用

4.位段在空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的;

5.位段涉及很多不确定因素,不跨平台,注重可移植的程序应该避免使用位段;

6.从低位向高位使用,一次开辟一个类型大小,当剩下比特位不够存放下一个成员时,丢弃剩余比特位再开辟新的内存。

功能:与结构体相同,不过更节省空间(不需对齐)。

2.1位段的内存开辟

struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 30;
};
int main()
{printf("%d\n", sizeof(struct A));//8return 0;
}

解释:先开辟一个int类型即32个比特位,_a使用2个比特位,剩30个比特位;_b使用5个,剩25个;_c使用10个,剩15个;_d需要30个,余下的比特位不足,舍弃;再开辟一个新的int类型即32个比特位,_d使用30个,剩2个;总共开辟64个比特位,即8个字节。 

2.2位段的内存分配

struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;printf("%d\n", sizeof((s)));//3
}

3.枚举

1> 不初始化默认为 0,1,2,…;也可以初始化(负值也可);若一开始初始化后面又不初始化,则后面按照顺序递增一

2> 与#define相比,枚举有类型检查,且也不参与运算;

3> 大小为一个整型大小,4个字节

enum Sex
{female=4,//是逗号不是封号male,secret=3//最后一个没有逗号也没有封号
};
enum Color
{red,green,blue
};
int main()
{enum Sex s = male;//male = 5;常量不能改printf("%d\n", female);//4printf("%d\n", male);//5printf("%d\n", secret);//3return 0;
}

4.联合(共用体) 

定义:一种特殊的自定义类型,包含一系列成员,特征是这些成员共用同一块空间,但是不能同时使用。

大小:1> 联合的大小至少是最大成员的大小
           2> 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍(同结构体)。

union UN
{char c;//两个成员共用同一块空间int i;//不能同时使用
};
int main()
{union UN un;printf("%d\n", sizeof(un));//4printf("%p\n", &un);//这三个地址相同printf("%p\n", &(un.c));//同上printf("%p\n", &(un.i));//同上return 0;
}

 

union UN1
{char arr[5];//5int i;//4
};
union UN2
{short str[7];//14int j;//4
};
int main()
{union UN1 un1;union UN2 un2;printf("%d\n", sizeof(un1));//8printf("%d\n", sizeof(un2));//16return 0;
}

//判断大小端

int check_sys()
{union UN{char c;int i;}un;un.i = 1;return un.c;
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}

要开学考啦,加油加油,再创辉煌!!

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

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

相关文章

广泛运用在工业、轨道交通、监狱的ip对讲终端

ip网络对讲系统是不同于传统广播、调频寻址广播和数控广播的产品&#xff0c;它是基于IP数据网络&#xff0c;将音频信号经过数字编码以数据包形式按TCP\IP协议在局域网或广域网上传送&#xff0c;再由终端解码的纯数字化单向&#xff0c;双向及多向音频扩声系统。 本产品是新一…

2023前端二面经典手写面试题

实现一个call call做了什么: 将函数设为对象的属性执行&删除这个函数指定this到函数并传入给定参数执行函数如果不传入参数&#xff0c;默认指向为 window // 模拟 call bar.mycall(null); //实现一个call方法&#xff1a; Function.prototype.myCall function(context…

LLaMA-META发布单卡就能跑的大模型

2023年2月25日&#xff0c;Meta使用2048张A100 GPU&#xff0c;花费21天训练的Transformer大模型LLaMA开源了。 1.4T tokenstakes approximately 21 days 以下是觉得论文中重要的一些要点 1&#xff09;相对较小的模型也可以获得不错的性能 研究者发现在给定计算能力限制的情…

《高性能MySQL》读书笔记(下)

目录 Mysql查询性能的优化 慢查询基础 优化数据访问 是否向数据库请求了不需要的数据 查询了不需要的记录 多表联查中返回全部列 MySQL是否在扫描额外的记录 重写查询的方式 切分查询&#xff08;重点&#xff09; 分解连接查询&#xff08;重点&#xff09; MySQL如…

史上最全的大数据开发八股文【自己的吐血总结】

自我介绍 我本硕都是双非计算机专业&#xff0c;从研一下开始学习大数据开发的相关知识&#xff0c;从找实习到秋招&#xff0c;我投递过100公司&#xff0c;拿到过10的offer&#xff0c;包括滴滴、字节、蚂蚁、携程、蔚来、去哪儿等大厂&#xff08;岗位都是大数据开发&#…

算法练习(七)数据分类处理

一、数据分类处理 1、题目描述&#xff1a; 信息社会&#xff0c;有海量的数据需要分析处理&#xff0c;比如公安局分析身份证号码、 QQ 用户、手机号码、银行帐号等信息及活动记录。采集输入大数据和分类规则&#xff0c;通过大数据分类处理程序&#xff0c;将大数据分类输出…

喜讯!华秋电子荣获第六届“蓝点奖”十佳分销商奖

2 月 25 日&#xff0c;由深圳市电子商会主办的2023 中国电子信息产业创新发展交流大会暨第六届蓝点奖颁奖盛典在深圳隆重举行。 图&#xff1a;华秋商城渠道总监杨阳&#xff08;右三&#xff09; 深圳市电子商会连续六年举办“蓝点奖”评选活动&#xff0c;旨在表彰对电子信…

高端电器新十年,求解「竞速突围」

竞争激烈的高端电器品牌们&#xff0c;平时王不见王&#xff0c;但也有例外。海尔、博西、海信、创维、方太、老板等等近乎中国电器行业所有一线品牌副总裁级别以上高层&#xff0c;2月22日都现身于上海&#xff0c;来参加一场由红星美凯龙攒起来的高端电器局&#xff0c;2023中…

能在软路由docker给部署搭建teamsperk服务器么?并且设置好ddns

参考链接(4条消息) 【个人学习总结】使用docker搭建Teamspeak服务器_blcurtain的博客-CSDN博客_teamspeak3 docker(⊙﹏⊙)哎呀&#xff0c;崩溃啦&#xff01; (tdeh.top)TeamSpeak服务器搭建与使用 - 缘梦の镇 (cmsboy.cn)Openwrt X86 docker运行甜糖-软路由,x86系统,openwrt…

虚拟数字人直播带货相比人工有哪些优势?

新经济时代的到来&#xff0c;彻底改变了传统的消费方式。虚拟数字人的出现&#xff0c;标志着新一波的消费升级到来。虚拟数字人直播带货&#xff0c;不仅降低了商家的带货成本&#xff0c;拉近了商家与消费者的距离&#xff0c;也给消费者带来全新的消费方式。 花西子虚拟形象…

如何查看Spring Boot各版本的变化

目录 1.版本 2.基础特性和使用 3.新增特性和Bug修复 1.版本 打开Spring官网&#xff0c;点进Spring Boot项目我们会发现在不同版本后面会跟着不同的标签&#xff1a; 这些标签对应不同的版本&#xff0c;其意思如下&#xff1a; GA正式版本&#xff0c;通常意味着该版本已…

k8s学习之路 | Day16 k8s 中的容器初探

文章目录容器镜像镜像名称镜像拉取策略私有仓库的拉取策略容器的环境变量和启动命令容器的环境变量容器的启动命令容器的生命周期钩子postStartpreStop容器的探针startupProbelivenessProbereadinessProbek8s 集群中最小的管理单元就是一个Pod&#xff0c;而Pod里面才是容器&am…

利用GPT-3 Fine-tunes训练专属语言模型

利用GPT-3 Fine-tunes训练专属语言模型 文章目录什么是模型微调&#xff08;fine-tuning&#xff09;&#xff1f;为什么需要模型微调&#xff1f;微调 vs 重新训练微调 vs 提示设计训练专属模型数据准备清洗数据构建模型微调模型评估模型部署模型总结什么是模型微调&#xff0…

JavaScript split()方法

JavaScript split()方法 目录JavaScript split()方法一、定义和用法二、语法三、参数值四、返回值五、更多实例5.1 省略分割参数5.2 使用limit参数5.3 使用一个字符作为分割符一、定义和用法 split() 方法用于把一个字符串分割成字符串数组。 二、语法 string.split(separat…

NCRE计算机等级考试Python真题(四)

第四套试题1、以下选项中&#xff0c;不属于需求分析阶段的任务是&#xff1a;A.需求规格说明书评审B.确定软件系统的性能需求C.确定软件系统的功能需求D.制定软件集成测试计划正确答案&#xff1a; D2、关于数据流图&#xff08;DFD&#xff09;的描述&#xff0c;以下选项中正…

RTMP的工作原理及优缺点

一.什么是RTMP&#xff1f;RTMP&#xff08;Real-Time Messaging Protocol&#xff0c;实时消息传输协议&#xff09;是一种用于低延迟、实时音视频和数据传输的双向互联网通信协议&#xff0c;由Macromedia&#xff08;后被Adobe收购&#xff09;开发。RTMP的工作原理是&#…

IP-GUARD控制台账户输入多次错误密码锁定后该如何解锁?

其他管理员账户给锁定了,暂时只能等其锁定时间到了才可以再次输入,默认是设置是锁定30min; 1、如果急需此账户查看,可以使用admin系统管理员账户登录控制台,在工具-账户中清除这个账户的密码,重新登录设置密码。

NIO与零拷贝

目录 一、零拷贝的基本介绍 二、传统IO数据读写的劣势 三、mmap优化 四、sendFile优化 五、 mmap 和 sendFile 的区别 六、零拷贝实战 6.1 传统IO 6.2 NIO中的零拷贝 6.3 运行结果 一、零拷贝的基本介绍 零拷贝是网络编程的关键&#xff0c;很多性能优化都离不开。 在…

【云原生kubernetes】k8s 常用调度策略使用详解

一、前言 通过之前的学习&#xff0c;我们了解到k8s集群中最小工作单位是pod&#xff0c;对于k8s集群来说&#xff0c;一个pod的完整生命周期是由一系列调度策略来控制&#xff0c;这些调度策略具体是怎么工作的呢&#xff1f;本文将详细讨论下这个问题。 二、k8s调度策略简介…

【多目标优化算法】多目标蚱蜢优化算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…