C语言之自定义类型——结构体详解

目录

1.为什么要有结构体?

2.结构体的声明:

结构体变量的定义

typedef与define

结构体变量的初始化

 结构体的存储原理

问题引入:

详解 

结构体成员偏移量的求解

 1.调用offsetof()函数实现

 2.通过宏模拟实现offsetof函数实现


1.为什么要有结构体?

这其实是因为事物有很多的性质,并且这些性质类型很有可能会不同,比如说:我们描述一本书时,便会定义书名(字符串)、作者(字符串)、书的价格(浮点型)等等,又如:描述一个学生时,我们会定义其姓名(字符串)、年龄(整型)、性别(字符串)等,那么这些能够描述同一事物的不同类型的数据类型便是结构体,这样能够使数据结构”高内聚,低耦合“。

2.结构体的声明:

我们以书为例:

 这里注意:如果创建的结构体是在函数外,那么类似于全局变量,在声明后的所有函数都能使用,而在函数内声明,则只能在本函数内部使用。

结构体变量的定义

结构体变量的定义一般是结构体加变量名,如:

这里的A就是结构体变量名,并且在这里我们还对A变量进行了整体初始化(初始化会一一对应)

 它的方式有多种,如:

 当然如果我们觉得每次定义都要写这么长很麻烦,我们可以用typedef进行类型重定义,如:

这里运用typedef 把struct book结构体类型转名为BK,也能实现相同的效果。这里讲到typedef,那就不得不与#define 进行对比了,这两者还是有区别的

typedef与define

#define是预处理时的宏命令指令,在预处理阶段会进行替换,而typedef 是关键字,在编译阶段处理,主要是进行类型的重定义,这里举个二者不同的典型例子:

 在上面定义的四个变量中,哪一个不是int*类型?

答案自然是b,为什么呢?因为typedef是类型替换,就是说可以把int*取了个别名叫int_ptr,这个int_ptr跟int,float这些一样都是类型,是独立的,因此c和d都是int*类型,而对于Int_ptr来说,它是宏定义的,它本身还是会被替换成int*,而对于int *a,b;句代码来说,*决定了类型,*a在一起,所以a是int*,而b前面没有*,所以是int类型,只有b前面也有*,这样b才会是int*类型。

我们还可以用匿名结构体定义变量,如:

 不过这样不能再定义新的变量。

结构体变量的初始化

对结构体变量的初始化,可以整体,也可以单独,如:

 也可以单独初始化,不过注意:对字符数组这样的,我们不可以直接赋值,而要用strcpy,如:

 哦对了,对结构体成员的访问,我们常用.和->,对于.我们可以理解成的,如上面的D.price可以理解成D的price,—>一般是地址寻问,如:

 结构体的存储原理

问题引入:

 请问上面代码的结果是多少,是4+1+4=9吗?

详解

对于结构体的存储,它其实得满足对齐规则,什么规则呢?

1.结构体的第一个成员位于结构体变量在内存中地址偏移量为0的地址处

2.其它成员(第二个成员往后所有成员)位于它的对齐数的整数倍的地址处(对齐数是成员的大小于默认对齐数的最小值,默认对齐数取决于编译器本身,如:vs 默认是8)

3.结构体总大小是所有成员的对齐数最大的那个的整数倍,

这里我们用上面的代码来解释:

 第一个是int类型,大小是4bit,所以是这样:

 对于b,是char类型,大小是1bit,默认对齐数是8,取小,所以会在1的倍数下开辟。如:

 

 对于c,大小是4bit,默认对齐数是8,取小,所以在4的倍数下开辟,如:

 所以结构体占0-11这12个bit,a,b,c的最大对齐数是4,而12正好是4的倍数,所以结果是12,

如图:

 当然,如果再加一个char d;如:

 此时应该是:

所以占0-15这些空间,共16bit,所以结果是16.如图:

结构体成员偏移量的求解

 1.调用offsetof()函数实现

offsetof函数是专门用来计算成员在type里的偏移量的,当然它的头文件是<stddef.h>

代码如下:

 

 运行结果:

 2.通过宏模拟实现offsetof函数实现

我们可以用0强制类型转换成相应的结构体类型的指针,那么相当于在0地址处申请了一个struct类型的地址,然后解引用出相应的成员地址,通过&取出该地址在强制转换成int,这样就实现了。

如下:

希望对您有所帮助!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值