在c语言中,学习自定义类型,有数组,结构体,联合体,枚举。现在咱们来讨论一下后三者。
结构体原型声明:
struct tag { member-list; }variable-list;
这样对于大都数没学过结构体的人来说看起来不是很懂。
那么咱们来具体的实例:
struct stu //stu为结构体名 { char name[20]; //成员 int age; //成员 };对于上面也是一个声明,那么怎么来定义结构体变量呢?
struct stu s;
这里的s就是结果构体变量,struct stu 就是类型。
那么怎么通过结构体来访问成员呢?结构体变量加点 例如:s.name s.age;
如果是结构体指针也可以通过->或者*p. 的方法来访问成员。
对于结构体初始化,可以在定义变量的时候初始化,例如:struct stu s = {"nihao",28};
对于重点掌握的是结构体内存对齐问题。
结构题内存的开辟像数组一样,在栈中开辟一段内存,从小到大依次分配。
而首成员的地址就是结构体的地址。
那么如何来计算结构体大小?那就要熟悉结构体中内存的对其规则:
有以下四点:
1.第一个成员在结构体变量偏移量为0的地方初。也就是说第一个成员地址与结构体地址相同。
2.其他成员变量要对其到某个对齐数的整数倍的地址处。
关于对齐数是编译器默认的一个对其数与该成员大小的比较值。在linux中默认对齐数为四,在vs中默认对齐数为八。当然也可以自己设定对齐数。
3.结构体总大小为最大对齐数的整数倍
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体整体大小就是所有最大对齐数的整数倍。
说完结构体内存对齐问题,来说说结构体传参问题。
就一句话,传参可以直接穿变量,但开销太大,所以传参一般传结构体地址。
位段与结构体类似,但是位段成员必须是int ,unsigned int ,signed int类型
位段就是一种用于节约内存空间的方法。
struct a { int a:2; int b:5; int c:10; int d:30; };
按照bit位来算,所以上面的结构体大小为8个字节。
枚举
顾名思义,就是一一列举,关键字为enum
enum { a, b, c=9, d, e };
a的值默认为0,b就等于1
而给c 赋值后d就等于10
用枚举的优点增加可读性和可维护性,防止命名污染。
联合体
联合体的特征就是成员公用了一段内存空间。
联合体的大小就是联合体内最大的成员大小。