可对于存储相同类型数据项的变量,我们可以用C数组。那么我们想存储不同类型数据项可以用什么呢,结构体是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。
在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问。
struct语句格式:
struct [structure tag] //结构标签,可写可不写
{
member definition; //标准的变量定义
member definition;
...
member definition;
} [one or more structure variables];//一个或者多个结构体变量,可选
举个栗子:
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
定义了结构体,接下来就要知道如何访问了。我们使用成员访问运算符(.)进行访问。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个点(英文状态下的句号)。我们可以使用 struct 关键字来定义结构类型的变量。下面我们演示了结构的用法:
#include <stdio.h>
#include <string.h>
struct Books /*定义结构体Books*/
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming"); /*strcpy:C语言的标准库函数实现字符串的复制*/
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 输出 Book1 信息 */
printf( "Book 1 title : %s\n", Book1.title);
printf( "Book 1 author : %s\n", Book1.author);
printf( "Book 1 subject : %s\n", Book1.subject);
printf( "Book 1 book_id : %d\n", Book1.book_id);
/* 输出 Book2 信息 */
printf( "Book 2 title : %s\n", Book2.title);
printf( "Book 2 author : %s\n", Book2.author);
printf( "Book 2 subject : %s\n", Book2.subject);
printf( "Book 2 book_id : %d\n", Book2.book_id);
return 0;
}
运行结果:
知道了结构体的定义以及访问,我们可以再进阶一些。使用结构体做函数参数,传参方式与其他类型的变量或指针类似。我们也可以使用上面实例中的方式来访问结构变量:
#include <stdio.h>
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 函数声明 */
void printBook( struct Books book );
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 输出 Book1 信息 */
printBook( Book1 );
/* 输出 Book2 信息 */
printBook( Book2 );
return 0;
}
void printBook( struct Books book )
{
printf( "Book title : %s\n", book.title);
printf( "Book author : %s\n", book.author);
printf( "Book subject : %s\n", book.subject);
printf( "Book book_id : %d\n", book.book_id);
}
运行之后结果和第一个栗子一样。
除了这些,我们还可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似:
struct Books *struct_pointer;
现在,我们可以在上述定义的指针变量中存储结构变量的地址:
struct_pointer = &Book1; /*为了查找结构变量的地址,& 运算符放在结构名称的前面*/
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符:
struct_pointer->title;
为加深理解结构指针的概念,我们用结构指针来重现上面的栗子:
#include <stdio.h>
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 函数声明 */
void printBook( struct Books *book );
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 通过传 Book1 的地址来输出 Book1 信息 */
printBook( &Book1 );
/* 通过传 Book2 的地址来输出 Book2 信息 */
printBook( &Book2 );
return 0;
}
void printBook( struct Books *book )
{
printf( "Book title : %s\n", book->title);
printf( "Book author : %s\n", book->author);
printf( "Book subject : %s\n", book->subject);
printf( "Book book_id : %d\n", book->book_id);
}
结构体还有很多妙用,比如结构体数组,即数组的每一个成员都是一个结构体。这个常常用在协议的定义上面。比如我们定义这样一个结构体:
#define DATA_LEN 2
#define LEN_MAX 3
typedef struct
{
uint8_t *cmd_name;
uint8_t cmd_length;
uint8_t cmd_sendnum;
uint8_t cmd_revnum;
uint8_t cmd_data[DATA_LEN ];
void (*Function)(void *Param);
}Protocol;
Protocol cmd_buf[LEN_MAX]=
{
{"cmd1",0x03,0x03,0x00,0x01,0x02,Function1},
{"cmd2",0x03,0x03,0x00,0x01,0x02,Function2},
{"cmd3",0x03,0x03,0x00,0x01,0x02,Function3},
}