一、创建结构体

1、结构体是是一些值的集合,这些值被称为成员变量。
2、结构体内的成员可以是不同类型的成员变量。
3、创建结构体

1
2
3
4
5
struct S{         //结构体名称
int a; //内部成员
char b; //内部成员
double c; //内部成员
};

4、结构体内部成员的访问:(1)结构体变量访问成员(结构变量的成员是通过点操作符(.)访问的.操作符接受两个操作数。如果s是结构体的具体名称,age 是其内部成员,则s.age就可以访问)。
(2)结构体访问指针变量的成员(定义一个指向该结构体的结构类型的指针ps,如果age是该结构体的内部成员,则(*s).age或者ps->就可以访问)。
5、结构体自引用:在结构体中可以包含该结构体本身的成员,具体的自引用如下:

1
2
3
4
5
struct NODE
{
int a;
struct NODE *next;
};

二、结构体初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Point
{
int x;
int y;
}a; //声明类型的同时定义变量a
struct Point b; //定义结构体b

struct Point c = {x,y}; //初始化:定义变量同时赋初值

struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = (10,{4,5},NULL); //结构体嵌套初始化

struct Node n2 = {20,{5,6},NULL};//结构体嵌套初始化

三、内存对齐

内存对齐原则:
1.第一个成员在结构体变量偏移量为0的地址。
2.其他成员变量对齐到对齐数的整数倍地址。VS默认8,linux默认4.
对齐数 = 与成员大小相比,取较小值。
3.结构体总大小为最大对齐数的整数倍。
4.如嵌套其他结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包括嵌套的结构体)的整数倍。
为什要内存对齐?
平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址 处取某些特定类型的数据,否则抛出硬件异常。
性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理 器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct S
{
char a; //从偏移地址0开始,0
int b; //占4个字节,与默认对齐数相比较小,对齐数取4,要从4的整数倍地址开始,4-7
char c; //8
}
总共9个字节,因为最大对齐数为4,所以总大小要是4的倍数,所以最终大小为12

struct S1
{
char a; // 0 1
char b; // 1 2
int c; // 4-7 4-7
}
最终大小 8

struct S3
{
char a; // 0
struct S1 s; // 结构体最大对齐数为4,从地址为4的整数倍开始算, 所以所占地址为 4-11
int c; // 12-15
}
最终大小 16

四、位段

位段成员必须是int,unsigned int,signed int

1
2
3
4
5
6
7
8
9
10
struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};
a占3位,b占4位,刚好占一个字节,剩下一位丢弃。
c占5位,d占4位,两个字节。
总共占3个字节。

五、枚举

将内容一一列举:

1
2
3
4
5
6
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};

六、联合

联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以 联合也叫共用体)可以用来判断大小端,以及ip地址转化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
union Un
{
char a;
int b;
};
int main()
{
union Un u;
u.b = 0x1;
if (u.a == 0x01)
{
printf("小端");
}
else
{

printf("大端");
}
return 0;
}

最后更新: 2019年05月31日 16:05

原始链接: http://CQolive.github.io/2019/05/31/结构体自定义类型总结/

× 请我吃糖~
打赏二维码