自定义类型——结构体
目录:
一、结构体类型
1.1结构体的声明
1.2 结构体的特殊声明
二、结构体内存对齐
三、结构体传参
四、结构体实现位段
4.1 什么是位段
4.2 位段的内存分配
4.3 位段跨平台和注意事项
正文开始:
一、结构体类型
结构体是一些不同类型值的集合,这些值称为成员变量。
struct定义的是结构体类型!类型!要创建结构体变量,要用结构体类型创建
例如:描述一个学生,有姓名、年龄、性别、学号,把这些放进用struct定义的结构体类型中就称为结构体的成员。
Stu是结构体类型名,结构体内只定义成员变量不赋值,结构体结尾一定要有逗号。
1.1 结构体类型的声明
一般情况下对应结构体成员创建的顺序进行初始化
如果我偏就不按顺序呢?
可以,前面加点结构体成员名再赋值
1.2 结构体的特殊声明
(1)匿名结构体:
结构体可以不完全声明,创建时不写结构体标签(名字),也就为匿名结构体。就像网上有很多网友发言,但是不显示他们真实姓名,以匿名形式发言。
匿名结构体只能使用一次,非特定需要最好不用。
s:表示用结构体类型直接创建一个结构体变量s,可直接用s点成员名赋值,匿名结构体s只能被使用一次
(2)typedef 重命名结构体
要创建结构体变量,每次总要写类型名struct Node创建,当结构体类型名过长可以typedef重命名结构体类型名为Node。下次可以直接拿Node代替struct Node创建结构体变量。
例如:一个叫张三的同学,平时大家都叫他小张,这两者指的都是同一个人。
(3)结构体的自引用
答案是:不行!因为Node是对结构体类型重命名产⽣的,但是在匿名结构体内部提前使⽤Node类型来创建成员变量,这是不⾏的。
解决方案如下:
二、结构体内存对齐
点击下方链接可进入我之前写的博客,学习内存对齐知识。
结构体内存对齐-CSDN博客
三、结构体传参
(1)传值调用
先创建一个结构体变量s,初始化,定义个函数print1打印结构体内每个成员数据。
因为打印结构体并不改变原始结构体的数据,所以传值过去可以
(2)传址调用
不改变数据用传值调用可以,那我用传址可以吗?
可以的,通过指针访问结构体的每个成员
打印结构体通过传值和传址都行,哪个好呢?
传值:
形参是实参的一份临时拷贝。我们定义的结构体中包含了一个大小为1000的数组,内存要为创建的结构体开辟空间,若传值实参占用内存有多大,形参也同样要拷贝同等大小的空间存储结构体内数据,而内存空间是有限的如果这样会占用很多内存空间造成空间浪费
传址:
不管实参结构体内存开辟多大空间,我始终传过去的是地址,是地址就用指针接收,一个指针开辟的空间根据当前环境的不同占用4或8个字节,在内存上比传值好得多。
总结:
四、结构体实现位段
4.1 什么是位段
位段的声明和结构体类似,有两个不同:
(1)位段的成员必须是 int、unsigned int 或 signed int ,在C99中位段成员的类型也可以选择其他类型。
(2)位段的成员名后面有一个冒号和数字。
例如:
A就是一个位段类型。位段类型里面的成员必须同一个类型,大部分情况下是int类型和char类型
冒号后面的数字表示这个成员占多少个比特位,例如_a原本占一个整型4字节,现在只占2个比特位。
4.2 位段的内存分配


4.3 位段跨平台和注意事项
(1)int 位段被当成有符号数还是无符号数是不确定的
(2)位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会出问题。
(3)位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
(4)当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利⽤,这是不确定的。
总结:
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在,要自己根据不同平台定义不同位段。
使用注意事项:
完