一、自定义类型
①结构体
②枚举
③联合体
二、枚举
注意创建好枚举类型后,里面可能的取值后面要用‘ ,’而不是‘ ;’
enum color//enum color 定义了一个名为 color 的枚举类型
{
RED = 1,//RED 被显式赋值为 1
GREEN,//GREEN 没有显式赋值,因此它的值是 RED 的值加 1,即 2
BLUE,//BLUE 同样没有显式赋值,它的值是 GREEN 的值加 1,即 3
};
int main()
{
enum color clr = GREEN;//定义了一个变量 clr,类型为 enum color,并将其初始化为枚举常量 GREEN
printf("%d\n", clr);
return 0;
}
三、联合体
①定义:联合体定义的变量包含一系列成员,这些成员共用同一块空间。所以联合体也叫:共⽤体。
union Un
{
char c;
int i;
};
int main()
{
union Un un = {0};
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
printf("%p\n", &un);
return 0;
}
②联合体内的成员共用同一块空间
三个printf输出的结果都是同样的地址,说明c和i共用一块空间就是第一个字节,但是使用时不能一起使用,(就像共享单车是公共的但是不能多个人一起使用)如下
再来验证Ⅰ:
union Un
{
char c;
int i;
};
int main()
{
union Un un = { 0 };
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}
字节是按小端存储的,存在内存中是44 33 22 11,而c和i共用了i的第一个字节,所以会将55放入进去
验证Ⅱ
int check()
{
union U
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret = check();
if (ret == 1)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
return 0;
}
会输出小端存储,因为i的二进制是00 00 00 01,由小端存储存在内存中是01 00 00 00,而u.c和i共用i的第一个字节的空间,也就是01,所以返回u.c就是返回1
补充:判断机器是小端or大端存储还可以利用char类型只占一个字节将1前面的字节取出来看返回的值,返回1说明01存在了小端
int check()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = check();
if (ret == 1)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
return 0;
}
③联合体大小的计算(也存在对齐)
联合的⼤⼩⾄少是最⼤成员的⼤⼩。
当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。
eg
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
Un1中 char c有5个字节的大小,int i有4个字节的大小,联合体共用一块空间的话难道Un1的大小就是5吗,不是的,因为char的对齐数为1,int的对齐数为4,这个联合体的最大对齐数为4,联合体的大小要是最大对齐数的整数倍,所以是8,浪费了3个字节的空间
Un2中short c有14个字节的大小,int i有4个字节的大小,联合体的大小为最大对齐数4的整数倍,又得满足放下最大成员c的14个字节,所以联合体大小是16
int main()
{
union U
{
char c1;
char c2;
char c3;
char c4;
char c5;
int i;
};
printf("%d", sizeof(union U));
return 0;
}
5个char类型的成员都和i共用i的第一个字节,最大的成员是4个字节,又是最大对齐数的整数倍,所以联合体的大小是4
这告诉我们什么,虽然联合体Un1中数组c的类型是char 【5】但是它的对齐数是看前面的char,为1!!!