《C语言进阶之自定义类型详解——结构体、位段、枚举、联合详解》

hello,各位小伙伴们大家好!

今天小风将带着大家进行C语言中有关结构的学习,在C语言的结构模块中包含结构体、位段、枚举、联合四大部分的内容,由于结构这一块的内容与数据结构的学习息息相关(重点)所以小风将会花比较大的篇幅讲解这块知识的内容(其中会穿插很多的图解尽可能的使大家能够吸收和理解)。

以下是本篇文章讲解的主要内容(大家可以根据实际所需进行检索):

结构体

  • 结构体类型的声明
  • 结构的自引用
  • 结构体变量的定义和初始化
  • 结构体内存对齐
  • 结构体传参
  • 结构体实现位段(位段的填充&可移植性)

枚举

  • 枚举类型的定义
  • 枚举的优点
  • 枚举的使用

联合

  • 联合类型的定义
  • 联合的特点
  • 联合大小的计算

目录

一、结构体

1.结构体类型的声明

1.1结构的基础知识

1.2结构的声明

1.3特殊的声明(匿名声明)

1.4结构体的自引用

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

1.6 结构体内存对齐(结构体所占空间大小的规则)

1.7结构体的传参

2.位段

2.1什么是位段

 2.2位段的内存分配

2.3 位段的跨平台问题

3.枚举

3.1枚举类型的定义

3.2枚举的优点

3.3枚举的使用

4.联合(共用体)

4.1联合类型的定义

4.2联合的特点

4.3 联合大小的计算


一、结构体

1.结构体类型的声明

1.1结构的基础知识

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

1.2结构的声明

声明方式一

struct tag  //"tag"指的是该结构提的类型名
{
    member-list;  //成员变量列表
}variable-list;  //这里指的声明的是该结构体变量,该处内容是可以省略,在后面定义结构体变量同样是可行的

 例如现在我们以这种方式来描述一个学生

struct Stu
{
    char name[20];//名字
    int age;//年龄
    char sex[5];//性别
    char id[20];//学号
}; //分号不能丢

声明方式二

//使用typedef进行重定义结构体类型
typedef struct tag  //重定义“struct tag”类型
{
    member-list;  //成员变量列表
}Tag;  //Tag -> 注意此时这里已不再是结构体变量了,而是结构体类型, 
       //此时等同于struct tag,可以用于声明结构体变量

 利用该种方式定义一个学生

typedef struct Stu
{
    char name[20];//名字
    int age;//年龄
    char sex[5];//性别
    char id[20];//学号
}Stu; //分号不能丢

 可能在这里有些小伙伴一定会有这样的一个疑问:这两种声明方式有什么区别和用途呢?

其实在这里其实它们本身并没有什么区别,都是声明了一个结构体变量,但相较于第一中声明方式第二种声明方式的优势在于当我们需要创建结构体变量时,不用再加上struct关键字,具体去别如下所示:

//方式一创建学生结构体变量
struct Stu student;


//方式二创建学生结构体变量
Stu student;

因此当我们需要创建多个结构体变量时,无疑是第二种方式更为方便和简洁。

1.3特殊的声明(匿名声明)

在某些结构体声明的时候,还可已进行不完全声明。如下:

//匿名结构体类型
struct
{
    int a;
    char b;
    float c;
}x;
struct
{
    int a;
    char b;
    float c;
}a[20], *p;

上面的两个结构在生命的时候省略掉了结构体标签(tag),而且我们通过观察可以发现这两个结构体的声明内容似乎是完全相同的。那么小风的问题来了:

//在上面代码的基础之上,下面的代码合法吗??
p = &x;

在这里我们一定需要注意编译器编译器会把上面的两个声明当成完全不同的两个类型,也就是说结构体指针变量p类型与结构体变量x的数据类型是不一致的,一定并不能想当然的将声明形式一样的两个结构体看成是等价的。

所以上面这段代码是不合法的!

1.4结构体的自引用

结构体的自引用可以理解为在结构体中它包含了自己。

问题思考:在结构中包含一个类型为该结构本身的成员是否可以呢,应该如何使用自引用才是正确的呢?

这里小风总结了一个判断是否可行的结论:如果我们在自引用过程中,自引用的结构体所占的空间大小是可以计算的,那么我们称这种自引用的方式是正确的,否则是不可行的。

例如下面这段代码

//代码1
struct Node
{
    int data;
    struct Node next;
};
//可行否?
//如果可以,那sizeof(struct Node)是多少?

这是一段错误的自引用方式,因为我们发现当我们想要

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

whelloworldw

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

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

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

打赏作者

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

抵扣说明:

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

余额充值