@TOC
一、结构体
1.结构体变量
struct s { char name[20]; int age; }p1,p2; int main() { struct s p3; return 0; }
p1,p2,p3都是结构体变量
但由于p1,p2在main外部定义 是全局变量
p3是局部变量
## 2.特殊声明
声明的时候 不完全声明 为匿名结构体类型
注意匿名结构体类型只能使用一次
#include<stdio.h> struct { char name[20]; int age; };
3.结构体的引用
1.嵌套调用
通过调用 pa变量 返回到stdent结构体中
#include<stdio.h> struct student { char name[20]; int age; char sex[20]; }; struct teacher { char name[20]; int age; struct student pa; char sex[20]; };
2.自引用
(1)无法做到自己调用自己 会无限套娃
#include<stdio.h> struct S { char name[20]; int age; struct S pa;//err }; int main() { struct S s; return 0; }
(2)若是想做到用本身类型访问下一个同类型结构体
使用指针指向下一个要访问的结构体
#include<stdio.h> struct s { int age; struct s*nest; };
三、结构体的初始化
这里的初始化很简单
就举一个嵌套调用的例子
#include<stdio.h> struct student { char name[20]; int age; char sex[20]; }; struct teacher { char name[20]; int age; struct student s; char sex[20]; }; int main() { struct teacher p={"张三","35",{"王五","16","男"},"男"}; printf("%s %d %s %d %s %s\n",p.name,p.age,p.s.name,p.s.age,p.s.sex, p.sex}; return 0; }
四、结构体的内存对齐
1.用法
1.第一个结构体成员放在 0偏移量处
2.若放在VS中 默认对齐数是8
后面的结构体成员 用其字节与默认对齐数比较 取小的为该结构体成员的对齐数 结构体成员放在对齐数整数倍的地址处
- 结构体的大小 是所有成员最大对齐数的整数倍
2.练习题
1.
#include<stdio.h> struct s { char a; int b; char c; }; int main() { struct s pa; printf("%d\n",sizeof(pa)); return 0; }
VS中默认对齐数是8
char a为1个字节 1<8 即a的对齐数是1 int b为4个字节 4<8 即b的对齐数是4 char c为1个字节 1<8 即c的对齐数是1 正常来说应取9个字节 9没有达到最大对齐数4的整数倍 故 要取 12
在这里插入图片描述
2.
#include<stdio.h> struct s2 { char c1; char c2; int i; } int main() { strcut s2 S; printf("%d\n",sizeof(S)); return 0; }
char c1为1个字节 1<8 即c1的对齐数是1 char c2为1个字节 1<8 即c2的对齐数是1 int i为4个字节 4<8 即i的对齐数是4 最大对齐数为4 因为最后也是取 8 是4的整数倍 即 8
在这里插入图片描述
3.修改对齐数
#include<stdio.h> #pragma pack(2) //将默认对齐数修改成2 struct s { char a; int b; char c; } #pragma pack() //将修改的对齐数消除 即只在上面的结构体生效 int main() { struct s pa={0}; printf("%d\n",sizeof(pa)); return 0; }
需要注意的是 对齐数是结构体成员在哪里进行偏转
偏转的大小是字节数
修改后 默认对齐数为2
char a为1个字节 1<2 即a的对齐数为1 int b为4个字节 4>2 即b的对齐数为 2
char c为 1个字节 1<2 即c的对齐数为1 最大对齐数为 2 但是结构最后是 7 不是2的整数倍 最后为 8
在这里插入图片描述
五、位段
## 1.用法
位段的成员必须是 int , unsigned int, signed int
成员名后必须有 冒号和数字
位段的空间是按照 int或者 char来开辟的
我们通常将 位段成员 按照 低比特位到高比特位传递
如果一块空间剩下的内容不够下一个成员使用 这块空间就会被浪费掉
## 2.练习题
#include<stdio.h> struct S { char _a:3;//a占两个比特位 char_b:4;//b占4个比特位 char_c:5;//c占5个比特位 char_d:4;//d占4个比特位 } struct S s={0}; s.a=10; s.b=12; s.c=3; s.d=4;
a为 10 -------- 1010--------->占3个比特位---010
b为 12 -------- 1100--------->占4个比特位---1100
c为 5 --------- 00101--------> 占5个比特位--00101
d为 4 ---------- 0010------------>占4个比特位---0010
在这里插入图片描述
六、联合体
1.用法
1. 一种特殊的自定义类型,主要表现为 成员共用一块空间
- 联合体的计算
联合体的大小至少是最大的成员的大小
当最大成员大小不是最大对齐数的整数时 就要对齐到最大对齐数的整数
2.练习题
1.正常算法题
VS默认对齐数为8
int a为4个字节, 4<8, a的对齐数为4
char b为1个字节 1<8 b的对齐数为1
a与b共用第一块空间 所以为4
又因为 4时是 最大对齐数4的整数倍 即 4
#include<stdio.h> union un { int a; char b; } int main() { union un pa; printf("%d\n",sizeof(pa));//4 return 0; }
在这里插入图片描述
### 2.用联合体判断大小端
#include<stdio.h> int move() { union un { int a; char b; }u; u.a=1; return u.b; int main() { int ret=move(); if(ret==1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }