自定义类型---->结构体,枚举,联合体
结构体:可以把不同类型的值存储在一起。
①结构体声明:
struct tag
{
member-list;
}variable-list;
在声明时,必须列出所有的成员(包含成员的类型和名字)。
例如:
struct
{
int a;
char b;
float c;
}x;
这个声明创建了一个名叫X的变量,它包含3个成员:a,b,c.
struct
{
int a;
char b;
float c;
}n[10],*m;
这个声明表示n是一个包含了10个结构体的数组。m是一个指针,它指向这个类型。
上面这两个都属于匿名结构体,它们只有结构体变量,没有标签。但是在使用时,建议标签和变量都写。
struct stu
{
int age;
char name[10];
char sex[5];
}student;
还有一种声明结构体的技巧,就是使用typedef创建一种新类型。
typedef struct
{
int a;
char n;
float s;
}xm;
这个和上面的区别是x是一个类型名而不是结构体的变量。所以后面的声明就可以写为下面这样:
xm p;
xm y[10],*m;
注意:如果要在多个源文件中使用同一种结构体,就可以把结构体声明放在一个头文件中,当源文件需要时,可以用#include头文件包含进来。
②结构体成员访问:通过(.)操作符来访问的。
比如访问上面最后一个例子:
xm.a = 10;
xm.n = 'q';
xm.s = 1.123;
在这里,还可以使用指向结构的指针来访问结构体成员。
比如上面包含指针的那个结构体:
m->a ;//(*m).a;这两种形式是等价的。
m->b;//(*m).b;
m->c;//(*m).c;
③结构体自引用:在结构体内部包含一个类型为它自己的成员。
struct S
{
int a;
struct S *b;//如果直接写b是错误的,因为不知道该结构体的大小,就无法开辟空间。
char n;
float s;
}x;
④结构体初始化:就像数组一样,可以用结构体变量进行整体初始化。
struct S
{
int a;
char n;
float s;
}x;
struct S x ={1,'w',1.32};
例如:
struct S
{
int a;
float s;
}x;
struct Node
{
int c;
struct S d;
struct Node *n;
}m;
struct Node m ={1,{2,1.34},NULL};
⑤计算结构体大小(重点)。
struct S
{
char a;
int s;
char b;
}x;
struct M
{
char a;
char b;
int s;
}m;
printf("%d\n",sizeof(struct S));
printf("%d\n",sizeof(m));
运行结果为:
计算结构体大小存在内存大小的问题,下面我们来讲述一下内存对齐的规则:
对齐数 = 编译器默认的一个对齐数 和 该成员大小的 较小值。
(VS中默认的值为8,Linux中的默认值为4)
结构体的总大小为最大对齐数的整数倍。
注意:1,第一个成员不需要对齐,但是第一个成员有对齐数,因为起始就是对齐的。
2,如果结构体中嵌套了结构体,嵌套的结构体的对齐数为其内部成员的最大对齐数。那结构体的整体大小就是所有对齐数(含有嵌套结构体的对齐数)的整数倍。
下面我们列举一个例子:
struct S
{
double a;
char s;
int b;
}x;
struct M
{
char q;
struct S b;
double s;
}m;
printf("%d\n",sizeof(m));
运行结果为:
结构体内存对齐:就是拿空间换取时间。
⑥结构体作为函数参数进行传参:
struct S
{
char s;
int b;
};
struct S x ={'w',23};
void print(struct S *p)
{
printf("%c\n",p->s);
printf("%d\n",p->b);
}
int main()
{
print(&x);
return 0;
}
运行结果是:
注意:在结构体传参时,要传结构体的地址,这样会提高代码的性能。
枚举
枚举:一一列举。把生活中的具有相同属性的放在一起。
使用的关键字:enum
enum Day
{
Mon,
Tues,
Wed,
Thur,
Fri=15,
Sat,
Sun
};
printf("%d\n",Mon );
printf("%d\n",Tues );
printf("%d\n",Wed );
printf("%d\n",Thur );
printf("%d\n",Fri );
printf("%d\n",Sat );
printf("%d\n",Sun );
运行结果是:
枚举类型默认取值从0开始,一次递增,也可以自己定义值,一次增加1。
联合体
联合体:它的所有成员公用同一块内存空间,所以其成员地址都是相同的。所以联合体的大小至少是其最大成员的大小。
但是联合体也存在内存对齐,对齐方式和结构体相同。
union s1
{
char a[4];
int q;
};
union s2
{
short m[5];
int d;
};
printf("%d\n",sizeof(union s1));
printf("%d\n",sizeof(union s2));
运行结果:
上一篇: Python中的logging使用
下一篇: java枚举类