您的位置:首页 > 其它

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

2017-12-03 12:08 453 查看
结构体:可以把不同类型的值存储在一起。

①结构体声明:

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

运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: