目录
一、结构体
1.1声明一个结构体
声明一个学生类型,目的是通过学生类型来创建学生变量(对象) <---标签 描述学生属性:姓名,电话,性别 <---成员变量
//Stu为标签 struct Stu { //定义成员变量 char name[20]; char tel[12]; char sex[10]; }; //创建全局变量 struct Stu s2; | //Wor为标签 struct Wor { //定义成员变量 char name[20]; char tel[12]; char sex[10]; }w1,w2,w3; //这个 w1,w2,w3 是全局变量 |
//匿名结构体变量 struct { int a; int b; float c; }x,*pa; |
1.2结构体自引用
1.2.1定义
//代码1
struct Node{
int data;
struct Node*next;
};
//代码2
typedef struct Node{
int data;
struct Node* next;
}Node;
1.2.2初始化
#include <stdio.h>
struct S
{
char c;
int a;;
double d;
char arr[20];
};
int main()
{
struct S s = {'c',1,1.0,"hello"};
printf("%c %d %lf %s",s.c,s.a,s.d,s.arr);
}
1.3内存对齐
1.第一个成员在与结构体变量偏移量为0的地址处
2.其他成员变量要对其某个数字(对齐数=编译器默认的对齐数与该成员大小的较小值)的整数倍地址处
3.结构体总大小为最大对齐数(每个成员变量头有的一个对齐数)的整数倍
4.如果嵌套了结构的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
1.3.1练习
//1.请输出下列结果 #include <stdio.h> struct S1 { char c1; int a; char c2; }; struct S2 { char c1; char c2; int a; }; int main() { struct S1 s1 = {0}; printf("%d\n", sizeof(s1));//12 struct S2 s2 = {0}; printf("%d\n", sizeof(s2));//8 return 0; }
如下图:
//2.请输入下列结果 #include <stdio.h> struct S2 { double c1; char c2; int a; }; struct S3 { char c1; struct S2 s2; double c2; }; int main() { struct S3 s3; printf("%d\n", sizeof(s3));//32 return 0; }
如图所示:
1.3.2设置默认对齐数
#include <stdio.h> #pragma pack(1) struct S { char c1; int d; }; int main() { struct S s; printf("%d", sizeof(s));//8 修改后->为5 }
1.3.3计算偏移量offsetof()
#include <stdio.h> #include <stddef.h> struct S { char c; int i; double d; }; int main() { printf("%d\n",offsetof(struct S,c));//0 printf("%d\n",offsetof(struct S,i));//4 printf("%d\n",offsetof(struct S,d));//8 return 0; }
1.3.4总结
要满足对齐,又要节省空间,要将占用空间空间较小的尽量集中在一起
1.4结构体传参
#include <stdio.h> struct S { char name; int age; char sex; }; void init1 (struct S *tmp) { tmp->name = 'w'; tmp->age = 100; tmp->sex = 'n'; } void print1(const struct S* tmp) { printf("%c %d %c",tmp->name,tmp->age,tmp->sex); } void print2(struct S tmp) { printf("%c %d %c",tmp.name,tmp.age,tmp.sex); } int main() { struct S s ={0}; //初始化 init1(&s); //传参 // 【传地址】 print1(&s); // 【传参数】 print2(s); return 0; }
1.5位段
//位段->节省空间 //位段不跨平台的(最大位不确定、左向右分配不确定) #include <stdio.h> struct S { int a : 2;//a只需要2个bit位 int b : 5;//b只需要5个bit位 int c : 10;//c只需要10个bit位 int d : 30;//d只需30个bit位 要 <= 32bit }; struct S1 { char a : 2;//a只需要2个bit位 char b : 5;//b只需要5个bit位 char c : 4;//c只需要4个bit位 char d : 8;//d只需8个bit位 要 <= 8bit }; int main() { struct S s; struct S1 s1; printf("%d\n", sizeof(s)); //输出:8 2bit+5bit+10bit+30bit=17bit+30bit > 32bit 17bit + 30bit < 4byte + 4byte = 8 printf("%d", sizeof(s1)); //输出:3 2bit + 5bit <= 1byte ,4bit <= 1byte ,8bit <= 1byte }
二、枚举
1.1初始化
enum Sex { //枚举的赋值初始化 MALE = 1, FEMALE = 2, SECRET = 8 }; enum Color { //从0开始递增 RED,//默认为0 GREEN,//默认为1 BLUE//默认为2 };
1.2优点
- 增加代码的可读性和可维护性
- 和#define定义的标识符(完全替换),比较枚举有类型检查,更加严谨
- 防止了命名污染(封装)
- 便于调试(在使用过程中间变量出问题,可直接找到错误位置)
- 使用方便,一次可以定义多个常量
三、联合体
1.1定义
联合体(共用体-[共用同一块空间]) union un { char c;//1字节 int i;//4字节 }; 联合体至少是最大成员的大小,则un占4个字节 运用时,只能用一个与struct不同
//与struct定义方法基本一致,可以匿名,可以定义变量u union { char c;//1字节 int i;//4字节 }; union { char c;//1字节 int i;//4字节 }u;
1.2计算联合体大小
//联合体计算 #include <stdio.h> union U { int a;//4本身占4字节,编译器默认8字节,占1个byte,最大对齐数为4,偏移4的整数倍 char arr[5];//本身5个连续1字节,但算的话,要算[元素]字节占1一个byte,默认编译器8字节.最大对齐数为1 //两者相加 4 + 1 < 8 }; int main() { union U u; printf("%d", sizeof(u));//8 }
目录