一、结构体(struct)
结构体是一种由程序员自己设计的数据类型,用于描述一个事物的各项数据,由若干个不同的基础类型组成。
设计:
struct 结构体名
{
类型1 成员名1;
类型2 成员名2;
...
};
定义结构体变量:
struct 结构体名 变量名;
结构体变量的初始化:
struct 结构体名 变量名={v1,v2,v3...};
必须要根据结构体设计时成员变量的顺序初始化,末尾缺少默认补零
struct 结构体名 变量名={.成员名1=v1,.成员名2=v2,...};
只初始化某些成员,可以不按照顺序初始化
struct 结构体名 变量名 = 结构体变量;
注意,同类型的结构体变量可以直接给结构体变量初始化、赋值
访问成员:
结构变量名.成员名
结构指针->成员名
结构变量作为形参时:
由于结构变量字节数较大,值传递效率较低,因此最好使用结构指针传递结构变量。
二、类型重定义(typedef)
typedef 的用法:
typedef 数据类型 变量名
可以直接使用变量名代替数据类型使用
typedef int INT;
INT a = 10;
typedef 常用于重定义结构体类型
typedef struct 结构体名 结构体
或者在设计的时候重定义
typedef struct 结构体名
{
...
}变量名;
之后就可以使用变量名代替typedef struct 结构体名
如何计算结构体的字节数:
结构体成员的顺序会影响结构体的成员数,如果能够在设计结构体时,合理安排成员顺序可以大大节约内存。
内存对齐:
假定第一个成员是从零地址开始,存储每个成员的地址编号必须满足能被该成员字节数整除,如果不能则填充空白字节。
内存补齐:
结构体的总字节数,必须是它成员类型的最大字节数整数倍,如果不是则在末尾填充空白字节。
在linux系统下计算结构体的对齐和补全时,如果成员的字节数超过了4字节,则按4字节计算
#pragma pack(n) 设置对齐、补齐的最大字节数(1,2,4)
windows系统是按照实际情况计算
三、联合(union)
联合与结构的使用方法基本一致,区别在于所有成员共用一块内存。
一个成员的值发生改变,其他成员的值也会随之发生改变,来达到节约内存的目的,现在基本不再使用。
联合的内存计算不用考虑内存对齐(因为共用一块内存),但需要考虑内存补齐。
union Data
{
char ch[5];
int num;
};//字节数是8
联合可以用于判断操作系统的大小端
假如十六进制整数0x01020304 存储在以0x0A起始的四个字节内存中
高位数据存储在高位地址:(0X0A:04 0X0B:03 0X0C:02 0X0D:01)小端系统
高位数据存储在低位地址:(0X0A:01 0X0B:02 0X0C:03 0X0D:04)大端系统
例:
union Data
{
char ch;
int num;
}
int main()
{
union Data data;
data.num = 0x01020304;
if(data.ch = 0x04)
{
printf("小端系统");
}
else
{
printf("大端系统");
}
}
个人计算机系统一般都是小端系统,而UNIN服务器和网络设备都是大端系统,本地字节序是小端模式,网络字节序是大端模式。
小端系统和大端系统共享数据需要序列化和反序列化(JSON\xml)。
四、枚举(enum)
枚举就是把一种数据类型可能出现的所有值全部罗列出来,取一个有意义的名字。
除此之外的数据,如果赋值给该枚举变量就是非法的(C语言为了运行效率,不会检查枚举是否合法,C++会)
#include<stdio.h>
enum Direction
{
UP = 183,
DOWN =184,
RIGHT = 185,
LEFT = 186
};
int main(int argc,const char* argv[])
{
printf("%d",UP);
}
如果不给成员值,枚举常量值从0开始,依次+1。如果某个设置了值,后面的会在该值的基础上依次+1。如果某个设置了值,后面的会在该值的基础上依次
为什么使用枚举:
为无意义的数值起一个有意义的名字,提高代码的可读性,并且有相对较高的安全性