结构体
1,结构体定义
#include <stdio.h> #include <string.h> #define STUDENT struct person //本质是替换字符串 STUDENT { //结构体的作用域是从上往下,可以嵌套定义,不可以整体引用,只能单个引用成员变量 int num; char name[30]; char sex; int age; char phone[20]; } stu1,stu2; //STUDENT person 只是结构体类型,不分配内存,无法赋值 // stu1和stu2是结构体变量,分配内存,可以赋值,类似于基本类型的赋值 /*struct person{ //结构体的作用域是从上往下 此时的person就相当于基本类型中的int int num; char name[30]; char sex; int age; char phone[20]; }; //在声明的时候,不分配内存,各个元素之间分别占据不同的内存单元,连续,但互不影响 struct { //无名称的结构体变量,只有创建有限个结构体变量,只能定义时就获取变量,没有创建变量,就没有任何意义 int num; char name[30]; char sex; int age; char phone[20]; }p1,p2,p3; */ void main(){ //初始化方式1 // struct person p; //在创建的时候,才分配内存空间 STUDENT p; // p ={10, 这种大括号赋值的初始化方式错误,只能在创建的时候,一起初始化 // "luoxu", // 'm', // 18, // "18041125454"}; p.num =10; //p.name ="luoxu"; //字符串不能这样复制,可以采用以下两种方式赋值 strcpy(p.name,"luoxu"); sprintf(p.phone,"181044225255"); printf("%s\n",p.name); printf("%s\n",p.phone); p.sex='m'; p.age =18; //初始化方式2 struct person p2 ={10,"luoxu",'m',18,"18041125454"}; //初始化3 struct { //无名称的结构体变量 int num; char name[30]; char sex; int age; char phone[20]; }p3 ={10, //无名称的结构体变量初始化3 "luoxu", 'm', 18, "18041125454"}; //初始化4 用另一个同类型的结构体变量初始化 struct person p4 =p2; }
2、结构体嵌套
#include <stdlib.h> #include <stdio.h> #include <string.h> //结构体变量的嵌套定义 struct person{ int num; char name[30]; struct student{ int num; char name[23]; char course[30]; }; //此处只是内部定义了student类型,没有创建student类型的变量,外部将无法引用,可以采用下面的方式创建成员变量 struct student stu; //stu的等级和num,name,course一样 struct teacher{ int num; char name[23]; char course[30]; }t1,t2; //t1,t2 的等级和stu,num,name,course一样 }; void main(){ struct person p; p.stu.num = 100; }
3、结构体数组
#include <stdlib.h> #include <stdio.h> #include <string.h> //结构体数组,每个元素都是结构体 struct person{ int num; char name[20]; float money; }p1[2] ={{1,"luoxu",100000.7},{2,"xiaoqing",100000.7}}; //第一种定义方式,有两个元素,每个元素都是地址 struct { int num; char name[30]; char phone[30]; }p2[2],p3[6]; //第二种匿名结构体的定义方式 void main(){ struct person p4[4]; //第三种定义方式 printf("%d,%d,%d\n", sizeof(int), sizeof(char [30]), sizeof(float)); //4,20,4 =28个字节 printf("%d,%d,%d\n", sizeof(p1), sizeof(p1[0]), sizeof(p1[1])); //56,28,28 printf("%x,%x,%x\n", &p1, &p1[0], &p1[1]); //403020,403020,40303c // 对于p1[0],p1[1]来说,一个结构体person变量占用的字节数是(4+20+4)= 28 //&p1, &p1[0]是一样的,他们与&p1[1]相差28个字节(1C= 16+12) //所以对于结构体数组来说,都是连续存储的 printf("%p,%p\n",p1[0],p1[2]); // 000000000061FD80,000000000061FD50 }
4、结构体指针
//结构体指针 struct person{ int num; char name[20]; }; void main(){ //结构体的方式访问 struct person per; per.num =100; strcpy(per.name,"luoxu"); printf("per.num = %d,per.name = %s,",per.num,per.name);//per.num = 100,per.name = luoxu //结构体指针的方式访问 struct person *p; //创建一个结构体指针变量,struct person 指明类型,从首地址往前读24个字节,以及如何解析 p = per; // 结构体名字代表结构体的首地址, p指向一个结构体,此时 (*p)= per; printf("(*p).num = %d,(*p).name = %s,",(*p).num,(*p).name);//(*p).num = 100,(*p).name = luoxu printf("p ->num = %d, p->name = %s,",p->num,p->name); //简化的方式 p ->num = 100, p->name = luoxu //per.name <=> (*p).name <=> p->name }
5、指向结构体数组的指针
#include <stdlib.h> #include <stdio.h> #include <string.h> //指向结构体数组的指针 struct person{ int num; char name[20]; float money; }; void main(){ struct person per[3] ={{1,"luoxu",1400004440.5}, {2,"xiaoqing",111004000.8}, {3,"xiaoqin",100000.7}, }; struct person *p; p = per; for (int i = 0 ; p < per+3, i < 3; ++p, ++i) { //p每次递增,加一个结构体的长度 printf("per.num = %d,per.name = %s\n,", per[i].num, per[i].name);//下标法 printf("(*p).num = %d,(*p).name = %s\n", (*p).num, (*p).name);//指针法 printf("p ->num = %d, p->name = %s\n", p->num, p->name); //指针法 } }
6、用指向结构体的指针作函数参数
用结构体变量的成员作参数----值传递,新建副本
用指向结构体变量或数组的指针作参数----地址传递
用结构体变量作参数----多值传递,效率低,也是值传递
#include <stdlib.h> #include <stdio.h> #include <string.h> //用指向结构体的指针作函数参数 //用结构体变量的成员作参数----值传递,新建副本 //用指向结构体变量或数组的指针作参数----地址传递 //用结构体变量作参数----多值传递,效率低,也是值传递,新建副本 struct person{ int num; char name[20]; float money; }; void changeStruct(struct person p){ //结构体属于复杂基本数据类型,不是指针或数组,有副本机制,新建一个结构体变量p,存储per[0]传过来的“值” // p.name = "Jobs"; 错误,字符串不能这样赋值 strcpy(p.name,"Jobs"); printf("p.num = %d,p.name = %s\n,", p.num, p.name); //p.num = 1,p.name = Jobs 改变成功 } void changeStructPointer(struct person *p){ strcpy(p->name,"Jobs"); printf("p->num = %d,p->name = %s\n,", p->num, p->name); //p.num = 1,p.name = Jobs 改变成功 } void main(){ struct person per[3] ={{1,"luoxu",1400004440.5}, {2,"xiaoqing",111004000.8}, {3,"xiaoqin",100000.7}, }; changeStruct(per[0]); //没有改变成功, printf("per.num = %d,per.name = %s\n,", per[0].num, per[0].name); //per.num = 1,per.name = luoxu changeStructPointer(&per[0]); //改变成功, printf("per.num = %d,per.name = %s\n,", per[0].num, per[0].name); //per.num = 1,per.name = Jobs }
7、内存动态分配
#include <stdlib.h> #include <stdio.h> #include <string.h> //内存动态分配 struct person{ int num; char name[20]; float money; }; void main(){ struct person *p = malloc(sizeof(struct person) * 10); //数组下标法读写数组 for (int i = 0; i < 10; ++i) { //写数据 p[i].num = i; sprintf(p[i].name,"luoxu%d",i); p[i].money = 1.1 *i; //读数据 printf("p[%d].num = %d,p[%d].name = %s,p[%d].money = %f\n", i,p[i].num,i, p[i].name,i,p[i].money); } //数组下标 +i 法读写数组 for (int i = 0; i < 10; ++i) { //写数据 (*(p+i)).num = i; //p[i] =(*(p+i)) sprintf((*(p+i)).name,"luoxu%d",i); (*(p+i)).money = 1.1 *i; //读数据 printf("p[%d].num = %d,p[%d].name = %s,p[%d].money = %f\n", i,(*(p+i)).num,i, (*(p+i)).name,i,(*(p+i)).money); } //指针法 for (int px = p, i =0 ; px < p+ 10, i < 10; ++p, i++) { //写数据 (*p).num = i; //p->num sprintf((*p).name,"luoxu%d",i); (*p).money = 1.1 *i; //读数据 printf("No.%d:(*p).num = %d,(*p).name = %s,(*p).money = %f\n", i,(*p).num,(*p).name,(*p).money); } }