深度剖析自定义类型:结构体,枚举,联合

每天进步一点点,坚持带来大改变!!!

 

目录

前言:

 1.结构体:

1.概念:

2.结构体的声明创建: 

3.特殊的结构体声明:

4.结构体的自引用:

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

6.结构体传参:

7.结构体内存对齐:

1.为什么存在结构体内存对齐?

2.修改默认对齐数:

8.结构体实现位段:

1.位段的概念:

2.位段的内存分配:

3.位段的跨平台问题:

4.位段的应用:

2.枚举:

1.枚举的概念:

2.枚举的定义:

3.枚举的优点:

3.联合(共用体):

1.联合的概念:

2.联合的特点:

3.联合笔试题:

4.联合体大小计算:

总结:


前言:

在C语言的语法中有许多的内置类型,包括字符型,短整型,整形,长整型,浮点型等数据类型,但这些数据类型只能单一描述事物的某个特征,当我们描述一个复杂的对象,我们可以创建自定义类型,用来描述事物的所有特征。

 1.结构体:

1.概念:

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

2.结构体的声明创建: 

struct Tag   //结构体类型

{

        member-list;  //成员列表

}variable-list;   //变量列表

例:描述一个学生:

  

3.特殊的结构体声明:

//匿名结构体类型:可以忽略结构体的标签

但是在定义变量的时候只能使用一次: 

struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
} *p;

虽然两个结构体的成员列表都相同,但是编译器会认为两个结构体类型不相同 

4.结构体的自引用:

结构体成员列表中包含一个结构体本身的类型:

原因:无法计算结构体本身的大小 

正确的自引用方式:

使用结构体指针 

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

 结构体嵌套定义和初始化:

6.结构体传参:

1.传值打印:

2.传址打印 :

传值和传址比较:传值时形参和实参都需要在内存中开辟空间,而传址的时候可以节约空间 

7.结构体内存对齐:

结构体变量在内存中的存储规则:

1.第一个成员存放在结构体偏移量为0的地址处;

2.其它成员变量存放到对齐数整数倍的地址处,

对齐数==编译器默认的对齐数与该成员大小的较小值 (VS默认对齐数为8)

3.结构体的总大小为最大对齐数的整数倍;

4.如果嵌套了结构体,嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体整齐大小就是所有最大对齐数的整数倍。

例1:

 c1存放到地址偏移量为0的地方,占一个字节,i占四个字节,默认对齐数为8,取其较小值为4,从偏移量为4的位置开始存放,c2占一个字节,默认对齐数为8,取其较小值为,存放到最大对齐数的整数倍处,结构体总大小为所有成员最大对齐数的整数倍处,最大对齐数为4,所以结构体总大小为12.

例2:

 c1从地址偏移量为0的位置开始占一个字节,s3是嵌套的结构体占16个字节,s3结构体中最大对齐数为8,所以对齐到8的整数倍处,d占8个字节,默认对齐数为8,取其较小值为8,所以对齐到8的整数倍处,结构体的总大小为所有最大对齐数的整数倍,最大对齐数为8,所以结构体总大小为32.

1.为什么存在结构体内存对齐?

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

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

总结:结构体内存对齐是为了拿空间换取时间

那如何做到既节省空间,又满足内存对齐?

让占用空间小的成员尽量集中在一起; 

2.修改默认对齐数:

可以通过编译器修改默认对齐数:

8.结构体实现位段:

1.位段的概念:

位段的声明和结构体相同,但是有两个不同:

1.位段的成员必须是 int、unsigned int ,signed int 或char.

2.位段的成员名后边必须有一个冒号和数字

例:

2.位段的内存分配:

1.位段空间大小的开辟是按照变量类型的大小一次开辟多大的字节;

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

char类型的变量一次开辟1个字节(8个bit位),将a,b存入之后,还剩下一个bit位,因为结构体总大小为3个字节,说明剩下的一个bit位被舍弃了。 

3.位段的跨平台问题:

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

4.位段的应用:

通过位段可以对以上数据在实现的时候节省大量的空间 

2.枚举:

1.枚举的概念:

将可能的取值一一列举:

如:一周的星期一到星期日是有限的7天,可以一一列举。

性别有:男、女、保密,也可以一一列举。

月份有12个月,也可以一一列举

2.枚举的定义:

enum day , enum sex都是枚举类型,{}中的都是枚举常量 

枚举常量默认从0开始,每次自增1,也可以赋初始值:

  

3.枚举的优点:

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

3.联合(共用体):

1.联合的概念:

成员公用一块空间

 

2.联合的特点:

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

 

 

3.联合笔试题:

判断当前计算机大小端:

 

4.联合体大小计算:

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

例:

 

总结:

以上是关于C语言自定义类型的所有内容,希望能够在C语言的学习路上能够帮助到你,互相促进,欢迎大家点赞,留言评论!

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linkindly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值