在C语言中,有一种类型听着很任性,叫做自定义类型。顾名思义,这种类型是程序员自己定义的一种类型,它和数组很相似,但也有一些区别。自定义类型包含以下几种:①结构体 ②枚举 ③联合
结构体就是将具有不同或相同的类型放在一起的聚合类型。
可能听着有些像顺口溜,上一段代码,捋一捋。
struct Peo
{
char name[20];
int age;
char sex[5];
char id[20];
}A;
在代码中我们定义了一个结构体,分开一一解读,Peo是结构体的标签(可以省略,但不建议省略)花括号内的是结构体的成员,可以有各种类型,A是结构体的名字。
结构体访问有两种方法: ①点操作访问 如:A.age; ②-> 访问 用于结构体指针的访问,比如:struct Peo *p=&a;p->a;
这里定义了一个结构体指针。
除此以外,我们还可以用 typedef struct来定义一个结构体,例如:
typedef struct Node
{
int data;
struct Node* next;
}Node;
在了解结构体如何定义的情况下,还应该知道结构体如何赋值:
Node={5}; 由于我们用typedef 定义的结构体,因此这里Node就是可以直接表示结构体,不用再次声明。
结构体如同数组一样,不能整体赋值,但可以整体初始化。
结构体有一个比较特殊亦或是比较奇怪的地方,就是结构体的内存对齐:
struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n",sizeof(struct S1)); //12
struct S2
{
char c1;
char c2;
int i;
};
printf("%d\n",sizeof(struct S2));//8
以上两段程序,内容一样,只是调整了顺序,最后打印出来的结果却不相同,若有异议,读者可自行实验。
这里是因为结构体有内存对齐的特质,所以输出结构不同。
结构体的内存对齐规则如下:
1、第一个成员在与结构体变量偏移量为0的地质处。
2、其他成员变量要对齐到(对齐数)的整数倍地址处。对齐数=编译器默认的一个对齐数与该成员大小的较小值。
在VS中默认值为8,Linux默认值为4
3、结构体总大小为最大对齐数的整数倍。
4、若嵌套了结构体情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。
掌握了这个规则,关于结构体的对齐数大体就不在话下了。 私下勤加练习,掌握的会蛮快的。
博主认为,结构体的内存对齐就是用空间来换取时间,有利有弊。
在结构体传参过程中,应当尽量传递结构体的地址,而不是将结构体整体作为参数传递过去。
因为在函数形参实例化的时候,会形成栈帧,当结构体过于庞大时,特别费时间,导致性能下降。
(关于函数传参详细过程,读者可自行参考https://blog.csdn.net/shadowh8/article/details/80271570 此篇博客
枚举: 枚举也只自定义类型中的一种,枚举顾名思义就是一一列举。
enum Day
{
Mon,
Tues,
Wed,
Thur,
};
枚举类型定义如此,{}里面的内容是枚举类型的可能取值,也叫枚举常量。
我们可以用#define定义常量,但相比较,枚举有如下有点:
1.增加代码的可读性和维护性。
2.枚举有类型检查,更加严谨。
3.防止了命名的污染。
4.便于调试。
5.使用方便,一次可以定义多个常量。
联合(共用体):
联合的特征是成员公用同一块空间,即所有成员的地址都是一样的,是第一个字节的地址。
//联合类型的声明
union un
{
char c;
int i;
};
关于联合大小的计算:
①联合的大小至少是最大成员的大小。
②当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
(关于对齐数的概念,在结构体中我们已经介绍过,这里就不必赘言过多。)
到此,自定义类型的相关概念就介绍完毕。 若有见解,欢迎随时指教。