全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这篇具有很好参考价值的文章主要介绍了全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

各位csdn的友友们肯定都掌握了c语言中char,short, int, long, float, double的类型,这些都是我们c语言中的一些内置类型,其实c语言是可以允许我们创造一些类型的,今天阿博就带领友友们一起掌握这些新的自定义类型😊😊😊

结构体

1.结构体类型的声明

2.结构的自引用

3.结构体变量的定义和初始化

4.结构体内存对齐

5.结构体传参

6.结构体实现位段(位段的填充&可移植性)

枚举

1.枚举类型的定义

2.枚举的优点

3.枚举的使用

联合

1.联合类型的定义

2.联合的特点

3.联合大小的计算

结构体类型的声明

struct stu
{
	char name[20];  //名字
	int  age;       //年龄
	char sex[5];    //性别
	char id[20];    //学号
};

注意最后那个分号千万不能丢哦!!!

这里的struct stu就是定义一个学生类型这里的name,age,sex,id就是成员变量,好了当我们了解这些后,就可以试着用结构体类型来创建变量了

struct stu
{
	char name[20];  //名字
	int  age;       //年龄
	char sex[5];    //性别
	char id[20];    //学号
}s4,s5,s6; 
int  main()
{
	struct stu s1;
	struct stu s2;
	struct stu s3;
}

友友们注意这里s1,s2,s3,s4,s5,s6都是我们用结构体创建出来的结构体变量,但是是s1,s2,s3是局部变量,s4,s5,s6是全局变量

结构体特殊的声明

struct
{
	char c;
	int a;
	double d;
}s1;
struct
{
	char c;
	int a;
	double d;
}*ps;
int  main()
{
	/*ps = &s1;*/   //error
	return  0;
}

以上两种结构体没有类型名,这就是传说中的匿名结构体了,友友们注意这种结构体定义出来的全局变量只能使用一次,还有虽然两个匿名结构体内容是相同的,但是我们也不能写*ps=&s1,因为在编译器看来,这两个地址类型是不一样的

结构体的自引用

/这是一个错误的示范
//struct Node
//{
//	int data;          //这里我们无法求得结构体的大小,它会无限循环下去
//	struct Node n;
//};
//int main()
//{
//	return  0;
//}
struct Node
{
	int data;   /*4*/
	struct Node* next;  /*4/8*/
};
int main()
{                        //正确的自引用方式
	struct Node n1;
	struct Node n2;
	 n1.next = &n2;
	 return  0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

typedef struct
{
	int data;
	char c;
}s;
typedef struct 
{
	int data;
	Node* next;    //error
}Node;
typedef struct Node
{
	int data;
	struct Node* next;   //correct
}Node;

注意typedef 是把struct 这个匿名结构体重新起名为s和Node,这里的s和Node是结构体类型名,不是定义的结构体变量!!!而且第二个typedef不能这样用,因为我们在没有重新命名Node之前,结构体变量中就使用了Node,这个顺序应放在命名之后使用!!!

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

struct S
{
	int a;
	char c;
}s1;       //全局变量
struct S s3;     //全局变量
struct C
{
	float f;
	struct S s;
};
int main()
{
	struct S s2={100,'q'};   //局部变量
	struct C sc = { 3.14f,{200,'w'} };     //结构体嵌套初始化
	struct S s3 = { .c = 'a',.a = 150 };   //注意这里我们也可以不按照顺序进行初始化
	return 0;
}

友友们注意结构体初始化的时候没有我们想象的那么复杂,其实就是定义变量的同时赋初值,不同的结构体初始化的时候可能是不相同的,因为它们所包含的类型可能不一样,结构体嵌套初始化的时候就是在大括号里面在加一个大括号然后进行赋初值

结构体内存对齐

友友们,重点来了哈,来一起和阿博打起12.1分的精神拿捏它吧🦹‍♂️🦹‍♂️🦹‍♂️

struct S1
{
	int a;
	char c;
};
struct S2
{
	char c1;
	int a;
	char c2;
};
struct S3
{
	char c1;
	int a;
	char c2;
	char c3;
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	printf("%d\n", sizeof(struct S3));
	return  0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
这里我们惯性思维会告诉我们是5, 6,7,但是当我生成结果的时候,可能会大吃一惊,下面来一起跟阿博探秘吧.这里阿博先给大家传输一些内功😁😁

1.结构体的第一个成员永远都放在0偏移处
2.从第二个成员开始,以后的每个成员都要对齐到某个对齐数的整数倍处,这个对齐数是成员自身大小和默认对齐数的较小值,在VS环境下默认对齐数为8,gcc环境下,没有默认对齐数,没有默认对齐数时,对齐数就是成员自身的大小.
3.当全部成员存放进去之后,结构体的大小必须是所有成员对齐数中最大对齐数的整数倍,如果不够,则浪费空间对齐.
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包含嵌套结构体的成员中的最大对齐数)的整数倍.

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
这里可以给友友们测试下,在测试前先给友友们介绍一个函数offsetof
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里我们也可以看出它们的偏移量.
2.
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
3.
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
4.

友友们我们来个结构体嵌套来测试一下我们的实力,加油哦😊😊😊

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里友友们可能会想为什么存在内存对齐呢,这里阿博分两方面给友友们讲.
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常.
2.性能原因 :数据结构(尤其是栈)应该尽可能的在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存仅需要一次访问.
总体来说:结构体内存对齐是拿空间来换取时间的做法.这里阿博可以教大家一种既满足对齐,又节省空间的做法:让占用空间小的成员尽可能的集中在一起

这里给友友们看下图解哦
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

修改默认对齐数

#pragma pack(1)    //设置默认对齐数为8
struct S1
{
	char  c1;//1,1,1
	int i;   //4,1,1
	char c2;  //1,1,1    //默认是1,就相当于没有对齐,结果是6
};
#pragma pack()  //取消设置的默认对齐数,还原为默认

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

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

结构体传参

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(const struct S*ps)   //防止被修改
{
	printf("%d\n", ps->num);
}
int main()
{
	print1(s);  //传结构体
	print2(&s); //传地址
	return  0;
}

这里友友们注意我们首选print2函数,因为函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销,如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降.所以结构体在传参的时候,要传结构体的地址.

结构体实现位段

什么是位段呢,可能会有很多友友疑问,因为我们都只知道段位😄😄😄,下面阿博就给大家普及一下
1.位段的成员通常是 int ,unsigned int ,signed int
2.位段的成员名后边有一个冒号和一个数字.

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
这里A就是一个位段.

//位段--二进制位
struct	A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};  //47 bit
int main()
{
	struct A sa = { 0 };
	printf("%d\n", sizeof(sa));
	return  0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里一共有47个比特位,按常理说6个字节,但为什么是8个字节呢,下面来和阿博一起探索吧

位段的内存分配

1.位段的空间上是按照需要以4个字节(int)或1个字节(char)的方式来开辟的
2.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里我们调试一下,发现和我们的假设一样,但是这只代表在vs上是这样,不代表其他编译器也是这样
位段的跨平台问题总结
1.int 位段被当成有符号数还是无符号数是不确定的
2.位段中最大的数目不能确定(16位机器最大16,32位机器最大32,写成27,在16位机器上就会出问题)

枚举类型的定义

enum Sex
{
	//枚举的可能取值 ,默认是从0开始,递增1的
	//枚举常量
	MALE=5,
	FAMALE,
	SECRET
};
int main()
{
	//enum Sex s=MALE;    //enum Sex=1;这里在c语言中是支持的,但是在c++中就不支持了
	printf("%d\n", MALE);
	printf("%d\n", FAMALE);  
	printf("%d\n", SECRET);
	return  0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里我们也可以改变它的初值,注意枚举常量是用逗号隔开的,最后一个逗号可以不加,枚举的好处可以让我们代码的可读性大大提高,枚举本身有类型检查,可以让我们的代码更加严谨,还便于我们代码的调试,一次可以定义多个常量

联合类型的定义

union Un
{
	char c;//1
	int i;//4
};
int main()
{
	union Un u;
	printf("%d\n", sizeof(u));
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	printf("%p\n", &u);
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

联合体的应用

#include<stdio.h>
union  Un
{
	char c;
	int a;
};
int main()
{
	union Un u;
	u.a = 1;
	if (u.c == 1)
	{
		printf("小端\n");
	}
	else
		printf("大端\n");
	return   0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

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

联合体大小的计算

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

union  Un
{
	char arr[5];   //5
	int n;        //4
};
int main()
{
	printf("%d\n", sizeof(union Un));
	return  0;
}

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

这里有5个char 的类型,大小是5,int 的大小是4,所以该联合体的大小至少是5,但是5不是4的整数倍,所以我们这里取了8个字节

这里给友友们出个题测试一下

union  Un
{
	short s[7];
	int n;
};
int main()
{
	printf("%d\n", sizeof(union Un));
	return  0;
}

这里有7个短整型,大小是14,有一个整形,大小是4,所以该联合体大小至少是14,但是14不是4的整数倍,所以需要往后浪费2个字节,所以大小是16

全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧
全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧

好了友友们,本期就到此结束了,如果你们感觉对自己有帮助的话,可以给阿博点个关注哦,后续阿博会继续给大家带来一些干货,下期再见💕💕💕文章来源地址https://www.toymoban.com/news/detail-416255.html

到了这里,关于全网最细的自定义类型详解(结构体,枚举,联合),友友们快来接收吧的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详解C语言自定义类型(结构体,枚举,联合)

    ❤️ 作者简介 :RO-BERRY 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识,对纯音乐有独特的喜爱 📗 日后方向 : 偏向于CPP开发以及大数据方向,如果你也感兴趣的话欢迎关注博主,期待更新 🎄结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不

    2024年02月16日
    浏览(40)
  • 【C语言】——自定义类型详解:结构体,枚举,联合

    大家好,今天为大家分享一下C语言中的那些自定义类型:结构体,枚举,联合,还有之前可能不曾了解的结构体内存对齐、位段等知识点!!! 一、结构体 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 结构的声明 : 例如描述一个学生

    2024年02月07日
    浏览(51)
  • C语言——自定义类型详解[结构体][枚举][联合体]

    我打算把结构体、枚举、联合体的重点内容总结一下,方便后期复习的时候能够更快,更准确的去拾取遗忘的知识。也希望能给大家起到借鉴的作用,不足的地方,请多多包涵。(不足的地方,也希望大家能够指出来) 结构体是一些值的集合,这些集合称为成员变量,结构体

    2024年02月13日
    浏览(42)
  • C/C++之自定义类型(结构体,位段,联合体,枚举)详解

    专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 个人主页:点我进入主页   1.前言 2.结构体 2.1结构体声明 2.2结构体初始化 2.3结构体的自引用 2,4结构体的内存

    2024年02月08日
    浏览(40)
  • 自定义类型:结构体,枚举,联合 (2)

    位段的出现就是为了节省空间。 位段的声明和结构是类似的,有两个不同: 1.位段的成员必须是 int、unsigned int 或signed int 。 2.位段的成员名后边有一个冒号和一个数字。 比如:  A就是一个位段类型,位段的位指的是二进制位,成员名后的数字代表着占空间的多少个bit位,

    2024年02月05日
    浏览(40)
  • 自定义类型之结构体,枚举,联合

    在初识结构体一文中,我们对结构体已经有所了解. 1.结构体的声明, 2.结构体变量的定义与初始化, 3.结构体传参. 其实结构体是一个很重要的内容,在数据结构中,应用十分广泛.所以学好 结构体 也是十分重要的! 匿名结构体是一种省略struct后面的类型名的一种结构体类型. 这种情

    2023年04月09日
    浏览(42)
  • 自定义类型:结构体、枚举、联合体

    结构体是一种自定义的数据类型,它由多个不同类型的成员变量组成,结构体可以将多个相关的数据打包在一起,方便进行管理和处理。 定义形式: struct 结构体名{ 类型 成员名1; 类型 成员名2; //更多的成员变量 }; 如描述一个学生: struct Stu这样就和int类型一样,都是数

    2024年02月16日
    浏览(41)
  • 【C语言】自定义类型:结构体、枚举、联合

    目录 前言: 一、结构体 (1)结构体的特殊声明 (2)结构体的自引用 (3)结构体嵌套初始化 (4)结构体内存对齐 (5)修改默认对齐数 (6)结构体传参 (7)位段 二、枚举 (1)枚举的定义 (2)枚举的优点 (3)枚举的使用 三、联合(共用体) (1)联合类型的定义 (

    2024年02月16日
    浏览(45)
  • C语言—自定义类型(结构体、枚举、联合)

    结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 实例一(描述一本书): 在声明结构的时候,可以不完全的声明。 实例一: 注:匿名结构体类型创建好之后只能用一次(没有标签构不成结构体类型) 实例一: 注:在结构中包含一个类型

    2024年02月06日
    浏览(46)
  • 【C语言进阶】自定义类型:结构体,枚举,联合

    1.1结构体类的基础知识 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.2结构的声明 例如描述一个学生: 1.3特殊的声明 在声明结构的时候,可以不完全的声明 上面的两个结构在声明的时候省略掉了结构体标签(tag) 当我们使用匿名结

    2024年02月07日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包