文章目录
一、结构体
结构体类型的声明
一般声明:
struct Book//结构体声明
{
char name[20];
int price;
char id[12];
};
int main()
{
struct Book b1;//是局部变量
return 0;
}
特殊声明:
匿名结构体类型(只能用一次)
//匿名结构体
struct
{
char c;
int i;
char ch;
}s;
//匿名结构体指针
struct
{
char c;
int i;
char ch;
}* ps;
结构体的自引用
struct Node
{
int d;//4byte
// struct Node n;非法
struct Node* next;//指向下一个同类型的结构体指针
};
结构体变量的定义和初始化
#include <stdio.h>
struct stu
{
char name[20];
int age;
double score;
}s = {"lisi", 20, 100};//结构体声明并定义变量s
int main()
{
struct stu s1 ={"zhangsan", 20, 85};//定义变量s1
struct stu* ps = &s1; //结构体指针ps指向s1的地址
printf("%s %d %lf\n",s.name,s.age,s.score);//一般方式打印结构体成员
printf("%s %d %lf\n",ps->name,ps->age,ps->score);//利用指针打印结构体成员
return 0;
}
结果如下:
结构体内存对齐
为什么存在内存对齐
内存对齐的规则
实际应用
//VScode环境下默认对齐数是8
#include <stdio.h>
struct S
{
char c;//1字节
int i;//4字节
};
struct SS
{
char c1;//1字节
int i;//4字节
char c2;//1字节
};
struct SSS//(相较于SS更节省空间)
{
char c1;//1字节
char c2;//1字节
int i;//4字节
};
struct SSSS
{
char c;//1字节
int i;//4字节
double d;//8字节
};
int main()
{
struct S s = {0};
struct SS s2 = {0};
struct SSS s3 = {0};
struct SSSS s4 = {0};
printf("%d\n", sizeof(s));//8字节
printf("%d\n", sizeof(s2));//12字节
printf("%d\n", sizeof(s3));//8字节
printf("%d\n", sizeof(s4));//16字节
return 0;
}
图解如下:
修改编译器的默认对齐数
#include <stdio.h>
#pragma pack(2)//预处理:将默认对齐数改为2
struct SS
{
char c1;//1个字节
int i;//4个字节
char c2;//1个字节
};
#pragma pack()//还原默认对齐数
int main()
{
printf("%d", sizeof(struct SS));//打印结果为8
return 0;
}
图解如下:
结构体传参
结构体实现位段(位段的填充&可移植性)
位段成员后面有一个冒号和一个数字
struct A
{
//int 4个字节-32bit
int _a:2;//_a成员占2个bit位
int _b:5;//_b成员占5个bit位
int _c:10;//_c成员占10个bit位
//int 4个字节-32bit
int _d:30;//_d成员占30个bit位(最大32bit)
};
二、枚举
枚举类型的定义
//枚举类型的每一项默认递增1,其中的常量可以自定义
#include <stdio.h>
enum Color
{
RED,
GREEN,
BLUE,
Yellow = 5,
Purple,
Pink
};
int main()
{
printf("%d ", RED);
printf("%d ", GREEN);
printf("%d ", BLUE);
printf("%d ", Yellow);
printf("%d ", Purple);
printf("%d ", Pink);
getchar();
return 0;
}
结果如下:
枚举的优点
枚举的使用
//以下代码仅供参考
#include <stdio.h>
enum Weekday
{
Mon = 1,
Tue,
Wed,
Thu,
Fri,
Sat,
Sun
};
int main()
{
int input = 0;
scanf("输入数字:%d",&input);
switch (input)
{
//case 1:
case Mon:
printf("Monday");
break;
case Tue:
printf("Tuesday");
break;
case Wed:
printf("Wednesday");
break;
case Thu:
printf("Thursday");
break;
case Fri:
printf("Friday");
break;
case Sat:
printf("Satday");
break;
case Sun:
printf("Sunday");
break;
default:
printf("input error");
break;
}
return 0;
}
三、联合
联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间
#include <stdio.h>
//联合体的声明
union Un
{
char c;//1
int i;//4
};
int main()
{
union Un u;//联合变量的定义
printf("%d\n", sizeof(u));//计算联合变量的大小
printf("%p\n", &u);//打印联合的地址
printf("%p\n", &(u.c));
printf("%p\n", &(u.i));
return 0;
}
结果如下:
原理如下:
联合的特点
联合的应用
联合经常用来判断大小端存储
大小端存储:
#include <stdio.h>
int check_sys()
{
union U
{
char c;
int i;
}u;
int i = 1;
return u.c;
//返回1 就是小端
//返回0 就是大段
}
int main()
{
int ret = check_sys();
if(ret==1)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
联合大小的计算
#include <stdio.h>
union Un
{
char a[5];
int i;
};
union un
{
char b[5];
char c;
};
int main()
{
union Un U;
union un u;
printf("%d\n", sizeof(U));//结果是8
printf("%d\n", sizeof(u)); //结果是5
return 0;
}