一、结构体的声明和使用:
结构是一种由程序员自己设计的数据类型,用于描述一个事物的各项特征数据,由若干个不同的基础类型组成。相当于把一些相互联系紧密的变量进行汇总。
下面是一个基本的结构声明:(注意最后的分号)
结构体类型名一般首字母大写,这样在定义变量时就不会与变量搞混。
struct 结构类型名
{
类型 成员名1;
类型 成员名2;
...
};
使用例:
struct Dog
{
char name[10];
int age;
char color[10;]
};
声明一般写在函数外,当进行多文件编程时,也可以写在头文件中,这样就可以在不同文件之间共用结构体。
在写完声明之后就可以使用其去构造变量,使用起来和int、char之流相似,也可加上*来构造指针变量:
struct Dog d1;//结构变量
struct Dog* d2;//结构指针
由于结构体内的内容可能很多,因此只占据很少内存的指针变量在向函数传递参数时能提高效率。
二、结构体的初始化
1、在定义定义结构变量时可以直接初始化:
struct 结构类型名 结构变量名 ={v1,v2,v3...}
2、注意初始化顺序一定要与成员顺序一致,如果采用下面这种方式,就不需要考虑顺序:
struct 结构类型名 结构变量名 ={.成员名=v1,.成员名=v2...}//不需要考虑顺序
3、 同类型的结构变量可以直接给另一个结构变量初始化。
三、结构体的调用
访问成员:
结构变量名.成员名;
d1.name;
由于结构变量一般字节数较大,普通的值传递效率很低,因此传递结构变量的地址,也即是 传递结构指针变量,此时通过结构指针变量访问内存时,借助->
结构指针变量 -> 成员名
d1->name;
如果不希望修改指针变量的成员值,可以使用const保护
四、使用typedef重定义结构类型名:
编程时常使用如下格式来声明:
typedef struct 结构类型名
{
} 结构类型名;
typedef struct Dog
{
}Dog;
这样之后定义结构变量可以不加struct:
Dog d1;
五、如何计算一个结构体的总字节数
结构成员顺序会影响整个类型的总字节数,如果能在设计结构体时合理安排成员顺序就能节约内存。
结构体内存遵循以下规律:
1、内存对齐:
假设第一个成员从零地址开始,则存储每个成员的地址编号必须能被该成员的类型字节数整除,如果不能整除则填充空白字节数
2、内存补齐:
总字节数要能被最大成员内存字节数整除,如果不满足则在末尾补空白字节
注意:
1、在linux32位系统下计算结构体的对齐和补齐时,如果成员的字节数超过4,则按照4字节计算对齐补齐//windows是按实际字节数对齐补齐
2、#pragma pack(n) 可以设置对齐、补齐的最大字节数为n,但n<4;
3、 结构体一般采用堆内存存储;
二、联合union
联合与结构的使用方法基本一致,区别是联合的所有成员共用一块内存。
一个成员的值发生改变,其他成员也随之改变。
联合的效果是使用少量内存存储多个标识符,以此达到节约内存的作用,但现在几乎不使用。
联合常考题:
union Data
{
char ch[5];
int num;
};
sizeof(union Date)==8
注意:计算联合总字节数时不考虑内存对齐,但仍需要考虑内存补齐。
如何判断系统的大小端?
0x01020304存在以0x0A~0x0D范围的四字节内存
大端系统:高位数据存储在低位地址(0x0D:0x04,0x0C:0x03...)
小端系统:高位数据存储在高位地址(0x0D:0x01,0x0C:0x02...)
个人计算机一般是小端系统,而UNIX服务器和网络设备都是大端;
常考编程题:
实现一个程序,判断系统是大端还是小端
union Data
{
int num;
char ch;
};
Data d;
d.num = 0x01020304;
if(0x04 == d.ch)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
三、枚举
枚举是一种数据类型,把可能出现的所有值罗列出来,并起一个有意义的名字表示这些值,除此之外给该变量赋其他值,是非法的(但不检查);可以看做一种值受限的int类型,但C编译器为了效率不检查,所以在C中枚举就相当于int类型变量。如果没有给初始值,那么默认第一个值从0开始,后面的值逐个+1;
enum Dire
{
UP=183,
DOWN=184,
RIGHT=185,
LEFT=186
}
enum Dire key=UP;
使用枚举为无意义的值取了一个有意义的名字,提高代码可读性,提高安全性(比变量安全)