引言
c语言给我们内置了很多数据类型(int char float long double), 但当我们需要描述一个复杂的对象时,比如一个人的升高 体重 年龄时发现内置的数据类型不能完成任务
所以c语言允许自定义类型 struct
结构体的定义
struct是关键字 Per是给结构体起的名字
结构体的使用
hadage是变量,该变量的类型是struct Per
hadage1是按结构体定义顺序初始化的
hadage2是使用操作符 . 指向你想要赋值的对象
hadage.age 指向的就是结构体定义的 int age;
匿名结构体
这个结构体只能使用halo这一个名字,也就是说这个结构体只能用一次,应为他并没名字你
无法创建变量赋值
结构体大小的计算
这个结构体的大小按我们的理解是不是应该等于9字节,4+1+4对吧,但当程序计算出来却是12,为什么呢 这就要涉及结构体对齐的问题了
结构体对齐
结构体的第一个成员对齐到和结构体起始变量偏移量为0的位置,其他成员要对其到和对齐数整数倍的地址 对齐数 = 成员类型大小 和 编译器默认对齐大小 中的较小值
所以上面那个结构体其实是这样计算的
那为什么要结构体对齐呢
1.不是所有硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处去某些
特定类型的数据,否则会有硬件异常
2. 性能原因,为了访问未对齐的内存,处理器需要做俩次内存访问,而对其的内存访问仅需要一次访问,因为若我们一次读8个字节,对齐了的只需要跳过若干个8字节就能一次读取,而若未对其
那这8个字节可能就分布在俩个8字节空间中,这样就需要读俩次在拼在一起在能读到
修改默认对齐数
vs的默认对齐数为8 我们可以使用#pragma修改
这样对齐数为1的时候 就和我们开始计算的一样了
改回默认对其数#pragma pack() 这样就行
位段
位段是以比特位单位设置变量的大小,追求的是极致的节省内存
a 的大小就是4比特,b 为 2 比特, 为3比特
位段大小计算
位段的成员可以int unsigned int signed int char
位段上的空间是按4字节(int) 或者1字节(char)开辟的
位段的空间大小遵循对齐规则
位端不能对其进行取地址操作,因为比特并没有地址
位段的可移植性很差 因为
位段的成员在内存中是从左向右 还是从右向左是取决于编译器的·
int是有符号还是无符号是不确定的
位段中的最大数目不确定
当位段剩下的空间是利用还是浪费是不确定的
枚举
枚举中的成员从上到下对应的值是从0开始的连续数 也就是给RED赋值给了0
应用
增加了代码可读性 便于调试 使用方便 遵循作用域规则,声明在函数 就只能在函数内使用