1、结构体的定义与声明
结构体的定义如下所示,struct
为结构体关键字,tag
为结构体的标志,member-list
为结构体成员列表,其必须列出其所有成员;variable-list
为此结构体声明的变量。为了简化结构体的使用,可以使用 typedef
来给结构体定义别名,从而在声明结构体变量时不需要重复使用 struct
关键字。
struct tag {
member-list
} variable-list ;
在一般情况下,tag、member-list、variable-list这3部分至少要出现2个。
例如,
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c //同时又声明了结构体变量s1 //这个结构体并没有标明其标签 struct { int a; char b; double c; } s1; //同上声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c //结构体的标签被命名为SIMPLE,没有声明变量 struct SIMPLE{ int a; char b; double c; }; //用SIMPLE标签的结构体,另外声明了变量t1、t2、t3 struct SIMPLE t1, t2[20], *t3; //也可以用typedef创建新类型 typedef struct{ int a; char b; double c; } Simple2; //可以用Simple2作为类型声明新的结构体变量 Simple2 u1, u2[20], *u3;
注意:如上面示例中,即使他们的成员列表是一样的,它们也是不同的类型。
2、嵌套结构体
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。
例如,
//此结构体的声明包含了其他的结构体 struct COMPLEX{ char string[100]; struct SIMPLE a; }; //此结构体的声明包含了指向自己类型的指针 struct NODE{ char string[100]; struct NODE *next_node; };
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明。
例如,
struct B; //对结构体B进行不完整声明 //结构体A中包含指向结构体B的指针 struct A{ struct B *partner; //other members; }; //结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明 struct B{ struct A *partner; //other members; };
3、没有成员变量的结构体
也可以定义一个空的结构体,有时候我们需要某一个结构体数据类型,但是暂时又不知道如何填充里面的成员变量,可以有如下定义:
struct Books { //TODO } book;
4、访问结构体成员
访问一个结构体成员变量,可以使用成员操作符(.
) ,
例如,
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ 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); /* print Book2 info */ 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; }
5、结构体作用
结构体和其他类型基础数据类型一样,例如int类型、char类型,只不过结构体可以做成想要的数据类型。以方便日后的使用。
在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新的类型。由于C语言内部程序比较简单,研发人员通常使用结构体创造新的“属性”,其目的是简化运算。
结构体在函数中的作用不是简便,其最主要的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。
6、结构作为函数参数
可以像基本数据类型一样,把结构体作为函数的参数。
例如,
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books book ); int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ printBook( Book1 ); /* Print Book2 info */ 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); }
7、结构体的指针
定义声明结构体指针格式如下,
struct tag *struct_pointer;
例如,
#include <stdio.h> #include <stdlib.h> /* 1.使用->引用结构体成员 */ int main () { struct Student { char cName[20]; int iNumber; char cSex; int iGrade; }student={"Girl",2017,'w',2}; struct Student *pStruct; pStruct = &student; //指向student结构体变量 printf("-----------the sudent's information----------\n"); printf("Name:%s\n",(*pStruct).cName); printf("Number:%d\n",(*pStruct).iNumber); printf("Sex:%c\n",(*pStruct).cSex); printf("Grade:%d\n",(*pStruct).iGrade); printf("============使用->符号引用结构体成员==============\n"); printf("Name:%s\n",pStruct->cName); printf("Number:%d\n",pStruct->iNumber); printf("Sex:%c\n",pStruct->cSex); printf("iGrade:%d\n",pStruct->iGrade); return 0; }
8、结构体数组
元素为结构体类型的数组称为结构体数组,在实际的应用过程中,经常使用结构体数组来表示具有相同数据结构的一个群体。
例如,
#include<stdio.h> #include<stdlib.h> //结构体中声明中尽量使用字符指针进行字符串操作,在初始化的时候会方便 //如果使用的是字符数组,那么会就要使用strcpy进行拷贝初始化 struct address{ char *country; char *city; }; struct teacher{ char *name; int age; struct address addr; }; void out_teacher(struct teacher tea); void out_all_teachers(struct teacher [],int num); int main(int argc,char *argv[]){ //先定义结构体变量,再进行定义结构体数组 struct teacher teacher_one = {"zhangsan",20,{"china","shanghai"}}; struct teacher teacher_two = {"lisi",25,{"china","hefei"}}; struct teacher teachers_one [] = {teacher_one,teacher_two}; out_all_teachers(teachers_one,2); printf("-----------------------------\n"); //在定义结构体数组的时候,直接进行结构体数组的初始化工作 struct teacher teachers_two [] = {{"wangwu",30, {"china","tianjin"}},{"zhaoliu",40,{"china","jiaozuo"}}, {"tianqi",50,{"china","shenzhen"}}}; out_all_teachers(teachers_two,3); return 0; } void out_teacher(struct teacher tea){ printf("name:%s",tea.name); printf("age:%d\n",tea.age); printf("country:%s\n",tea.addr.country); printf("city:%s\n",tea.addr.city); } void out_all_teachers(struct teacher teachers[],int num){ int i = 0; for(i = 0; i < num ; i++){ out_teacher(teachers[i]); printf("======================\n"); } }
9、结构体占用内存空间
结构体变量的所占用内存空间的大小为各成员变量所占空间之和,使用sizeof
查看占用内存空间大小。
例如,
1)没有成员变量的结构体计算大小
#include <stdio.h> #include <string.h> struct Books { }; int main( ) { printf("%d\n", (int) sizeof(struct Books)); /*0*/ return 0; }
2)有成员变量结构体计算大小
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main() { printf("%d\n", (int) sizeof(struct Books)); /*204*/ return 0; }