本文作者:一颗带有痣的毛
本文内容:详细讲解结构体
前言
一、结构体是什么?
结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量
二、结构体的声明与使用
1.结构体的声明,以及特殊声明
假设你想声明一个学生类型的结构体,那么你应该怎么声明呢?首先学生是不是应该有姓名,学号,年龄,性别等,既然知道了这么多那么我们开始声明啦!
struct student { char name[20];//姓名 int age;//年龄 char sex[5];//性别 char num[15];//学号 };
好啦,最简单的结构体声明就这么完成啦,最重要的我们还是得注意,声明结构体的时候,我们应该在结尾处放上一个分号,这样才是一个完整的结构体的声明噢!
再告诉大家一个小tips吧,关于结构体的声明,也有一类是特殊的结构体声明,就是说,我们声明的时候可以忽略结构体标签,就类似于下方操作。
struct { char name[20];//姓名 int age;//年龄 char sex[5];//性别 char num[15];//学号 }x;
我们声明结构体的时候,编译器也不会发生报错提醒的噢!
2.区分正确与错误的自引用
首先,我们来思考一个问题,在结构中包含一个类型为该结构本身的成员是否可以呢?同学们,你们要永远清除一句话,实践是检验真理的唯一标准,遇到拿捏不稳的问题的时候,我们可以去实践出真知,去实践一下吧!
#include<stdio.h> struct node { char name; struct node next; }; int main() { printf("%d", sizeof(struct node)); return 0; }
我们将该段代码放到编译器中发现,编译器居然直接给我们报了一个错误,我们是用来未定义的struct node,那么我们现在就只想用这个类型,那可怎么办呢?其实在c语言中,有一种叫结构体指针,就可以完美的解决这一问题,接下来我将在底下进行代码的演示!
#include<stdio.h> struct node { char name; struct node* next; }; int main() { printf("%d", sizeof(struct node)); return 0; }
像如上代码,我们就可以正常的使用啦,相信再看的小伙伴,也一定会去动手实践一下滴对吧!
三.结构体变量的定义和初始化
首先,我们应该清楚,在任何时候我们都需要定义一个变量,以及对这个变量进行相应的初始化,那么接下来,我们就应该进行实际的操作啦!
首先我们先进行结构体的初始化啦
#include<stdio.h> struct student //类型声明 { int x; char name[20]; }; int main() { struct student s1 = { 0 }; return 0; }
一定要记住,在进行声明变量的时候一定要记性初始化!
那么结构体应该怎么样的形式定义呢?
首先我们需要理解的是结构体的类型声明其实就是刚开始的结构体的定义也就是struct student,这个我们可以理解为int == struct student,理解完这个之后,我们已经进行了类型的声明了不是,所以前面我们应该还要加上类型名也就是struct student s1
#include<stdio.h> struct student { int x; char name[20]; }; int main() { struct student s1 = { 0 }; return 0; }
四.结构体内存对齐
这个时候,我们已经大差不差的了解了什么是结构体,以及结构体的声明以及定义了,这个时候,我们来深入的讨论一个问题,那就是计算结构体的大小,首先我们来看一道小小的例题吧!
#include<stdio.h> struct student { char i; int j; char k; }; int main() { printf("%d", sizeof(struct student)); return 0; }
按正常的思维来说,我们应该认为该内存大小为1+4+1,也就是6对吧,可是事实真的是这样吗?我们来进行编译看一下
我们会发现此时的结果是12,这是为什么呢?
接下来,我们来给大家普及一个知识,就是结构体的对其规则:
1.第一个成员在与结构体变量偏移量为0的地址处
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
对齐数=编译器默认的一个对齐数与该成员大小的较小值
3.结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
好啦,既然我们已经知道了这么多了,那么我们是不是就应该进行实际的解释了呢!话不多说,我们直接上图!
上面的一个图代表的是一般人的习惯性思维,但是实际上却不是这样,在内存中,我们会牺牲自己的空间,来换取时间,那么正确的思考方式是什么样的呢?
如上图所示,我们正常情况应该是会自动补齐该内存的限制的,就比如说此时的char是1,但是我们呢想一下哈,在我们中最大的是不是int,int是不是四个字节,所以我们要以我们最大对齐数为例,我们的char也要对齐到4个字节的位置,所以会自动补齐三个空格,那么问题我们是不是就迎刃而解了啦!
那么接下来,我在考大家一个问题呢?如果是以下的代码,那么我们的sizeof大小还会是12吗?
#include<stdio.h> struct student { char k; char i; int j; }; int main() { printf("%d", sizeof(struct student)); return 0; }
证明:
我们会发现结果居然不是原来的12了,啊,这是怎么一回事?难不成,我们刚才的分析都分析错误了吗?我们在接着进行该代码的分析
正如上图所示,在内存当中,我们应该让占用空间小的成员尽量的集中在一起,这样的话,假设我们的最大对齐数是四,那么首先,我们就可以直接的进行存储,前两个一个字节的数据,这样我们就可以牺牲空间换取时间啦!
总结
今天的初始结构体就到此结束啦,本次的讲解包含结构体的声明、定义、以及结构体变量的初始化,以及结构体在内存中的对齐!本文到此就结束啦!!!