欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义类型---->结构体,枚举,联合体

程序员文章站 2022-05-12 11:29:31
...

结构体:可以把不同类型的值存储在一起。

①结构体声明:

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));

运行结果:

自定义类型---->结构体,枚举,联合体