0x00 前言
文章中的文字可能存在语法错误以及标点错误,请谅解;
如果在文章中发现代码错误或其它问题请告知,感谢!
0x01 结构体类型的定义
在实际编程过程中,我们希望把一些关联的数据存放在一起,这样方便我们使用,但是这些数据的类型有时候并不一致,例如报文内容以及该条报文长度,报文内容和长度不属于同一类型,报文应该是类似如char*类型的字符串,报文长度应该是类似如int类型的整数。
因为数组只能存放同一类型的数据,所以不适合用数组来保存这些变量。 但在C语言中,结构体允许将不同类型数据组成组合型的数据结构。此时,我们若想要将类型不一样的关联数据存放在一起,就可以使用结构体。
声明一个结构体类型的一般形式如下:
struct 结构体类型名
{
成员表列
};
其中,成员表列中的每个成员(Member)是该结构体类型所包含的变量或数组,上面所说的报文内容和报文长度可以是一个结构体的成员,它们组合在一起构成成员表列,举例如下:
struct UDP_Server_Thread_Para
{
void *pData;
int Len;
};
结构体的类型可以有很多种,结构体类型中的成员由开发者自己定义,并且成员不用初始化。
另外,一个结构体成员可以属于另一个结构体类型,例如:
struct TIME
{
int date;
int month;
int year;
int hour;
int min;
int sec;
};
struct nmea_msg
{
struct TIME utc;
char gpssta;
int longitude;
int latitude;
short speed;
short altitude;
};
0x02 结构体类型变量的定义
上节所述的结构体类型本身并不会作为数据而被系统分配内存,如果一个结构体类型定义了变量则系统会分配内存空间,每一个结构体变量的所占内存大小,由结构体类型中的每个成员的总和决定。
定义结构体变量的方法有三种:
1.先声明结构体类型,再定义该类型变量:
一般形式为:
struct 结构体类型名
{
成员表列
};
struct 结构体类型名 变量名表列;
例如:
struct UDP_Server_Thread_Para
{
void *pData;
int Len;
};
struct UDP_Server_Thread_Para UDPThreadPara1,UDPThreadPara2;
为了便于理解,可以把struct UDP_Server_Thread_Para 类型类比于 int类型,UDP_Server_Thread_Para UDPThreadPara1,UDPThreadPara2即int UDPThreadPara1,UDPThreadPara2。
一个在该定义方式下的程序例子:
#include<stdio.h>
struct UDP_Server_Thread_Para
{
void *pData;
int len;
};
int main()
{
struct UDP_Server_Thread_Para UDPThreadPara1,UDPThreadPara2;
UDPThreadPara1.pData = "hello";
UDPThreadPara1.len = 1;
UDPThreadPara2.pData = "world";
UDPThreadPara2.len = 2;
printf("UDPThreadPara1: %s, len %d\n", (char*)UDPThreadPara1.pData, UDPThreadPara1.len);
printf("UDPThreadPara2: %s, len %d\n", (char*)UDPThreadPara2.pData, UDPThreadPara2.len);
return 0;
}
运行结果:
2.在声明的同时定义变量:
一般形式为:
struct 结构体类型名
{
成员表列
}变量名表列;
例如:
struct UDP_Server_Thread_Para
{
void *pData;
int Len;
}UDPThreadPara1,UDPThreadPara2;
声明和定义变量放在一起比较直观,但在比较大的代码工程中,为了使程序结构清晰,会对类型声明和变量定义放在不同的位置。另外,在此方式下,也可以根据需要在函数中新增该结构体类型变量。
一个在该定义方式下的程序例子:
#include<stdio.h>
struct UDP_Server_Thread_Para
{
void *pData;
int len;
}UDPThreadPara1,UDPThreadPara2;
int main()
{
UDPThreadPara1.pData = "hello";
UDPThreadPara1.len = 1;
UDPThreadPara2.pData = "world";
UDPThreadPara2.len = 2;
struct UDP_Server_Thread_Para UDPThreadPara3; //新增该结构体类型变量
UDPThreadPara3.pData = "!!!!";
UDPThreadPara3.len = 3;
printf("UDPThreadPara1: %s, len %d\n", (char*)UDPThreadPara1.pData, UDPThreadPara1.len);
printf("UDPThreadPara2: %s, len %d\n", (char*)UDPThreadPara2.pData, UDPThreadPara2.len);
printf("UDPThreadPara3: %s, len %d\n", (char*)UDPThreadPara3.pData, UDPThreadPara3.len);
return 0;
}
运行结果:
3.不指定类型名直接定义结构体类型变量:
一般形式为:
struct
{
成员表列
}变量名表列;
struct
{
void *pData;
int Len;
}UDPThreadPara1,UDPThreadPara2;
这种方式只能够定义一次,不能再以此定义其它变量。
一个在该定义方式下的程序例子:
#include<stdio.h>
struct
{
void *pData;
int len;
}UDPThreadPara1,UDPThreadPara2;
int main()
{
UDPThreadPara1.pData = "hello";
UDPThreadPara1.len = 1;
UDPThreadPara2.pData = "world";
UDPThreadPara2.len = 2;
printf("UDPThreadPara1: %s, len %d\n", (char*)UDPThreadPara1.pData, UDPThreadPara1.len);
printf("UDPThreadPara2: %s, len %d\n", (char*)UDPThreadPara2.pData, UDPThreadPara2.len);
return 0;
}
运行结果:
0x03 结构体类型变量初始化和引用
对于结构体变量的初始化即赋值,可以在定义结构体变量时对其进行成员初始化,例如:
struct UDP_Server_Thread_Para
{
void *pData;
int Len;
}UDPThreadPara1={“I LOVE CHINA”,12},UDPThreadPara2={“I AM CHINESE”,12};
也可以引用 结构体变量时赋值,格式如下:
结构体类型变量名.成员名
例如:
struct UDP_Server_Thread_Para
{
void *pData;
int Len;
}UDPThreadPara1,UDPThreadPara2;
UDPThreadPara1.pData = "I LOVE CHINA";
UDPThreadPara1.Len = 12;
UDPThreadPara2.pData = "I AM CHINESE";
UDPThreadPara2.Len = 12;
若结构体成员本身又属于另一个结构体类型,则需要运算符“.”逐级找到最低以及的成员赋值。比如上一小节nmea_msg类型结构体中utc属于TIME类型结构体,假设现在要为speed以及month赋值则:
struct TIME
{
int date;
int month;
int year;
int hour;
int min;
int sec;
};
struct nmea_msg
{
struct TIME utc;
char gpssta;
int longitude;
int latitude;
short speed;
short altitude;
} Data;
Data.speed = 50;
Data.utc.month = 12;
最后,需要注意的是,访问结构体成员需要对齐访问,至于这个概念 ,下篇博文会介绍。
以上。
参考文档:
1.http://c.biancheng.net/cpp/html/88.html
2.https://www.runoob.com/cprogramming/c-structures.html
3.https://blog.csdn.net/xiaoyali/article/details/4393486
4. 谭浩强.C程序设计(第四版)[M].北京:清华大学出版社,2010.