结构体内存对齐
解释1 从内存开始位置存放
解释二 int对齐数是4 vs默认对齐数是8 取其较小值的倍数 那就是4的位置存放
char 对数1 vs是8默认 谁的较小值对数是1 那就是任意数 所以c2防砸8 如下图绿色部分
struct S2
{
char c1;
int i;
double d;//8
};
输出结果16
struct S4
{
double d;
char c;
int i;
};
struct S4
{
double d;
char c;
int i;
};
struct S5
{
char c1;
struct S4 s4;
double d;
};
printf("%d\n", sizeof(s5));//32
如果发生嵌套 偏移量取最大对齐数 比如s4最大时double8,把算出的16填入从8开始。最终的对齐数取两个的最大对齐数
设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到
让空间小的成员尽量集中在一起
修改默认对齐数
默认对齐数是8
把默认对齐数改为2
#pragma pack(2)
struct S
{
char c1;//0
1-3 浪费
int i;//4-7
char c2;//8
9-11 浪费
};
#pragma pack()//这里是取消掉
#pragma pack(1)
struct S
{
char c1;//1 1 1
int i;//4 1 1
char c2;//1 1 1
};
#pragma pack() //结果6
int main()
{
printf("%d\n", sizeof(struct S));//
return 0;
}
offsetof
#include <stddef.h>
struct S
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d\n", offsetof(struct S, c1));//c1相对于这个结构体成员的偏移量.相当于起始位置
printf("%d\n", offsetof(struct S, i));
printf("%d\n", offsetof(struct S, c2));
return 0;
}
结构体传参
结构体传参 传递地址更好
结构体实现位段
位段成员必须是int ,unsigned int或signed int 还能见到char类型
A是一个位段类型 那位段A的大小是多少
一个整形32个bit位
struct A
{
//4个字节 - 32bit 根据位段的内存分配 int开辟一个整形来分配以下空间 如果不够就在开辟
int _a : 2;//_a 成员占2个bit位
int _b : 5;//_b 成员占5个bit位
int _c : 10;//_c 成员占10个bit位
//15
//4个字节 - 32bit 这里只剩15个放不下30个所以有开辟了一个 随意开辟两个整形总共8个字节
int _d : 30;//_b 成员占30个bit位
};
16位 - int - 2byte - 16 bit
32位 - int - 4byte - 32 bit
int main()
{
printf("%d\n", sizeof(struct A));//8
return 0;
}
struct S
{
char a : 3;
char b : 4;
char c : 5;
char d : 4;
};
int main()
{
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
return 0;
}//结果为 62 03 04
由以上的出 一个字节内部数据在使用的时候先使用低地址 在使用高地址 从右向左。当一块空间有剩余不够使用的时候直接浪费掉就行
位段的应用
节省空间
枚举 (一一列举的意思)
#define RED 5
#define GREEN 8
#define BLUE 9
//声明枚举类型
enum Color
{
RED=5,//5 默认递增1 可给赋初值
GREEN=8,//8
BLUE//9
};//可能取值放在枚举类型 常量
int main()
{
//CPP 语法检查更加严格
enum Color c = BLUE;//颜色的可能取值赋给c
printf("%d\n", sizeof(c));
/*printf("%d\n", RED); 0
printf("%d\n", GREEN);1
printf("%d\n", BLUE); 2*/
printf("%d\n", Color::RED); //枚举类型大小就是个整形变量 打印4
return 0;
}
枚举引用
void menu()
{
printf("*****************************\n");
printf("**** 1. add 2. sub *****\n");
printf("**** 3. mul 4. div *****\n");
printf("**** 0. exit *****\n");
printf("*****************************\n");
}
enum Option
{
EXIT,//0
ADD,//1
SUB,//2
MUL,//3
DIV//4
};
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
break;
case SUB:
break;
case MUL:
break;
case DIV:
break;
case EXIT:
break;
default:
break;
}
} while (input);
return 0;
}