前言:
类型
1、内置类型
char
short
int
long
long long
double
2、自定义类型
当内置类型不能够满足需求的时候,支持自定义一些类型
1>结构体
2>枚举
3>联合体
一. 结构体类型的声明
1.1 结构体的概念
结构体是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.2 结构体的声明
举例描述⼀个学⽣:
struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }s3,s4;//全局变量 int main() { struct Stu s1 ,s2;//局部变量 return 0; }
1.3 特殊的声明
在声明结构的时候,可以不完全的声明。
⽐如:
//匿名结构体类型 struct { int a; char b; float c; }x; struct { int a; char b; float c; } *p;
上⾯的两个结构在声明的时候省略掉了结构体标签(tag)。
那么问题来了?
//在上⾯代码的基础上,下⾯的代码合法吗? p = &x;
解析:不合法,会出现警告: 编译器会把上⾯的两个声明当成完全不同的两个类型,所以是⾮法的。
注:匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。
1.4 结构体的初始化
struct Stu { char name[20];//名字 int age;//年龄 float score;//成绩 }s3,s4;//全局变量 int main() { struct Stu s1 ={"zhangsan",20,98.5f}; struct Stu s2={.age=22,.name="lisi",.score=93.0f}; return 0; }
1.5 结构的自引用
以上链表中存储1的结构叫一个节点。
在结构中包含⼀个类型为该结构本⾝的成员是否可以呢?
⽐如,定义⼀个链表的节点:
struct Node { int data; struct Node next; };
上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不⾏的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤⼩就会⽆穷的⼤,是不合理的。
正确的⾃引⽤⽅式:
struct Node { int data; struct Node* next;//下一个节点的地址 };
sizeof(stcurt Node)大小就可以计算了
在结构体⾃引⽤使⽤的过程中,夹杂了typedef对匿名结构体类型重命名,也容易引⼊问题,看看下⾯的代码,可⾏吗?
typedef struct { int data; Node* next; }Node;
答案是不⾏的,因为Node是对前⾯的匿名结构体类型的重命名产⽣的,但是在匿名结构体内部提前使⽤Node类型来创建成员变量,这是不⾏的。
解决⽅案如下:定义结构体不要使⽤匿名结构体了
typedef struct Node { int data; struct Node* next; }Node;
二. 结构体内存对⻬
我们已经掌握了结构体的基本使⽤了。
现在我们深⼊讨论⼀个问题:计算结构体的⼤⼩。
这也是⼀个特别热⻔的考点: 结构体内存对⻬
下面我们看这样一个例子
struct S1 { char c1; int i; char c2; }; struct S2 { char c1; char c2; int i; }; int main() { struct S1 s1 = { 'a',100, 'b'}; struct S2 s2 = { 'a','b','100' }; printf("%zd\n", sizeof(s1)); printf("%zd\n", sizeof(s2)); return 0; }
这俩个结构变量类型和数据一样,只是顺序不一样,那么大小会一样码?
输出:
我们发现大小不同,它们是如何分配空间的呢?
这就涉及到内存对齐!
2.1 对齐规则
首先先得掌握结构体的对齐规则:
1. 结构体的第⼀个成员对⻬到相对结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
- VS中默认的值为8
- Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的
整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构
体的整体大小就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
由对齐规则对上面程序分析有:
2.11 练习1
struct S3 { double d; char c; int i; }; int main() { printf("%d\n", sizeof(struct S3)); return 0; }
解析:根据分析可知,double的对齐数 8,char对齐数 1,int 对齐数 4,首先double放8个字节,紧接连续放char,此时地址到8了,下一个地址位9,9不是4的倍数,所以放在地址12,放四个字节。共16个字节,16是结构体最大对齐数8的倍数,所以答案是16
输出: