C 结构体的定义

#include<stdio.h>structstudent{intID;charname[10];intage;};//注意这里的分号intmain(){//初始化structstudentstudent1={1111,"Redhat",20};structstudentstudent2={.ID=1111,.name="Debian",.age=20};//C99才有structstudentstudent3={1111,"BSD",.ID=20,.age=30};//ID=20//使用printf("%d,%s,%d\n",student1.ID,student1.name,student1.age);printf("%d,%s,%d\n",student2.ID,student2.name,student2.age);printf("%d,%s,%d\n",student3.ID,student3.name,student3.age);}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out1111,Redhat,201111,Debian,2020,BSD,30







结构体内存分配情况

小的遵循大的数据类型,存在浪费内存的情况

#include<stdio.h>#include<string.h>structstudent{unsignedcharc1;unsignedcharc2;unsignedinti1;unsignedcharc3;unsignedcharc4;unsignedcharc5;unsignedcharc6;unsignedinti2;};intmain(){printf("%ld\n",sizeof(structstudent));structstudentstudent1;memset(&student1,0x55,sizeof(structstudent));student1.i1=0x12345678;student1.i2=0x23456789;student1.c1=0x21;student1.c2=0x22;student1.c3=0x23;student1.c4=0x24;student1.c5=0x25;student1.c6=0x26;int*p=(int*)&student1;for(inti=0;i<sizeof(structstudent)/4;i++){printf("%p%x\n",p,*p);p++;}}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out160x7ffc7913b1c0555522210x7ffc7913b1c4123456780x7ffc7913b1c8262524230x7ffc7913b1cc23456789可以看到内存初始化就是0X55,第一个的4个字节存在了浪费



结构体,自定义数据类型:

#include<stdio.h>#include<string.h>structstudent{unsignedcharc1:1;unsignedcharc2:3;unsignedcharc3:4;};intmain(){printf("%ld\n",sizeof(structstudent));structstudentstudent1;student1.c1=1;student1.c2=6;student1.c3=14;char*p=(char*)&student1;printf("%x,%d,%d,%d\n",*p,student1.c1,student1.c2,student1.c3);}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out1ffffffed,1,6,14




结构体嵌套:

#include<stdio.h>#include<string.h>structman{unsignedcharage;};structstudent{unsignedcharname[20];structmana_man;};intmain(){printf("%ld\n",sizeof(structstudent));structstudentstudent1;student1.a_man.age=10;printf("studentage=%d\n",student1.a_man.age);}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out21studentage=10



结构体数组,结构体嵌套

#include<stdio.h>#include<string.h>structman{charname[20];unsignedcharage;unsignedcharheiget;};structhuman{structmanson;intmoney;};intmain(){printf("%ld\n",sizeof(structhuman));/*结构体数组*/structmanpeople[3]={{"奥巴马",50,170},{"金正恩",44,166},{"朴槿惠",33,155},};/*结构体嵌套*/structhumana_human;a_human.son.age=10;printf("sonage=%d\n",a_human.son.age);}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out28sonage=10




结构体赋值

#include<stdio.h>#include<string.h>structman{charname[20];unsignedcharage;unsignedcharheight;};intmain(){structmanpeople1={"奥巴马",50,170};structmanpeople2;people2=people1;//结构体的赋值,people1的内存赋值到了people2,二者相互独立!//memcpy(&people2,&people1,sizeof(people1));//相当于memcpy(&people2,&people1,sizeof(people1));printf("%s,%d,%d\n",people2.name,people2.age,people2.height);////////////////////////////////////////////////////////*区别于数组charstr1[10]={"Hello!"};charstr2[20];str2=str1;//这是不允许的。数组的名仅是一个地址,不允许赋值。////////////////////////////////////////////////////////这个不是赋值,这个只能是指向了那个地址charstr3[]={"Hello!"};char*p1=str3;char*p2=p1;*/}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out奥巴马,50,170






结构体赋值里面的指针变量

#include<stdio.h>#include<stdlib.h>#include<string.h>structman{char*name;unsignedcharage;unsignedcharheight;};intmain(){structmanpeople1={"朴槿惠",40,170};structmanpeople2;people2=people1;//结构体赋值printf("%s,%d,%d\n",people2.name,people2.age,people2.height);people2.name="王麻子";//指针指向常量"王麻子"printf("%s,%d,%d\n",people2.name,people2.age,people2.height);/*结构体指针*/structmanpeople3;people3.name=malloc(20);strcpy(people3.name,"孙悟空");printf("%s,%d,%d\n",people3.name,people3.age,people3.height);//free(people3.name);//堆释放会对下面的strcpy(people4.name,people3.name);有影响/*如果结构体里面有指针,不能通过简单赋值完成操作,因为指向的是一样的*/structmanpeople4;people4.name=malloc(strlen(people3.name)+1);strcpy(people4.name,people3.name);people4.age=people3.age;people4.height=people3.height;printf("%s,%d,%d\n",people4.name,people4.age,people4.height);free(people3.name);//堆释放free(people4.name);//堆释放}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out朴槿惠,40,170王麻子,40,170孙悟空,0,0孙悟空,0,0




结构体指针 初步1

#include<stdio.h>#include<stdlib.h>#include<string.h>structman{char*name;unsignedcharage;unsignedcharheight;};intmain(){structmanpeople1;structman*people2=&people1;(*people2).name=malloc(10);(*people2).age=20;(*people2).height=170;/*上面的形式可以写成一下:*/people2->name=malloc(10);people2->age=20;people2->height=170;}编译通过chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outchunli@ubuntu:~/pointer$



结构体指针 初步2

#include<stdio.h>#include<stdlib.h>#include<string.h>structman{unsignedcharid;charname[20];unsignedcharheight;};intmain(){structmanpeople[3]={{1,"wang",181},//wang属于常量{2,"li",182},{3,"zhang",189},};/*定义一个结构体指针*/structman*people2=&people[0];printf("%d,%s,%d\n",people2->id,people2->name,people2->height);/*访问方式2,也可以方便for循环*/printf("%d,%s,%d\n",people2[1].id,people2[1].name,people2[1].height);people2++;//一次会移动一个结构体printf("%d,%s,%d\n",people2->id,people2->name,people2->height);/*structmanpeople1={1,"wang",181};structmanpeople2={2,"wang",181};structmanpeople3={3,"wang",181};不要尝试用循环来遍历这样的数据,因为您不知道编译器是怎么安排的最好放在同一个数组里面*/}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out1,wang,1812,li,1822,li,182




结构体的指针,初步3

#include<stdlib.h>#include<string.h>structman{unsignedcharid;char*name;unsignedcharage;};intmain(){structman*sp=malloc(sizeof(structman));sp->id=5;sp->age=10;sp->name=malloc(10);strcpy(sp->name,"zhang");printf("%d,%s,%d\n",sp->id,sp->name,sp->age);free(sp->name);//一定先释放这个free(sp);//要不然sp-name永远找不到了return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out5,zhang,10








动态获取用户输入,不会浪费内存空间

#include<stdio.h>#include<stdlib.h>#include<string.h>structtest{char*name;//指针哦};structman{unsignedcharid;char*name;unsignedcharage;//structtest*p;//有嵌套了一层,这是很难搞的};intmain(){structman*sp=malloc(sizeof(structman)*10);memset(sp,0,sizeof(structman)*10);//内存清零for(inti=0;i<10;i++){sp[i].id=i;sp[i].age=i;charbuf[999]={0};scanf("%s",buf);intlen=strlen(buf);sp[i].name=malloc(len+1);sprintf(sp[i].name,"%s",buf);}for(inti=0;i<10;i++){printf("%d,%s,%d\n",sp[i].id,sp[i].name,sp[i].age);}for(inti=0;i<10;i++)//循环释放{free(sp[i].name);}free(sp);//全部释放return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out1211111111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222222aswsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvmmcsfdmcdsmc'nvvnvpmvpwvm[sdvfsdvdvdfefdff0,12,01,1111111111111111111111111111111111111111111111111111111111111111111,12,2222222222222222222222222222222222222222222222222222222222222222222,23,a,34,s,45,wsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvm,56,mcsfdmcdsmc'nv,67,vnvpmvpwvm[sdv,78,fsdv,89,dvdf,9




形参是结构体的函数

#include<stdio.h>#include<stdlib.h>#include<string.h>structman{unsignedcharid;char*name;unsignedcharage;};voidfun1(structmana_man){printf("id=%d,age=%d,name=%s\n",a_man.id,a_man.age,a_man.name);strcpy(a_man.name,"haha");//会影响传过来的数据,因为指向的是同一块内存a_man.id=99;//而id就不会发生变化}intmain(){//structmanpeople1={0,"wang",100};structmanpeople1;people1.id=0;people1.age=10;people1.name=malloc(10);strcpy(people1.name,"wang");fun1(people1);printf("id=%d,age=%d,name=%s\n",people1.id,people1.age,people1.name);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outid=0,age=10,name=wangid=0,age=10,name=haha





结构体参数,地址与传值

chunli@ubuntu:~/pointer$catmain.c#include<stdio.h>#include<stdlib.h>#include<string.h>structman{unsignedcharid;charname[100];unsignedcharage;};voidfun1(structmana_man)//传值过来{printf("id=%d,age=%d,name=%s\n",a_man.id,a_man.age,a_man.name);strcpy(a_man.name,"haha");//无法修改a_man.id=99;//无法修改}voidfun2(structman*sp)//地址传过来//voidfun2(conststructman*sp)//保护起来,防止修改{printf("id=%d,age=%d,name=%s\n",sp->id,sp->age,sp->name);strcpy(sp->name,"鲁智深");//可以修改sp->id=66;//可以修改}intmain(){structmanpeople1;people1.id=0;people1.age=10;strcpy(people1.name,"wang");fun1(people1);//fun1无法修改参数值printf("id=%d,age=%d,name=%s\n",people1.id,people1.age,people1.name);fun2(&people1);printf("id=%d,age=%d,name=%s\n",people1.id,people1.age,people1.name);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outid=0,age=10,name=wangid=0,age=10,name=wangid=0,age=10,name=wangid=66,age=10,name=鲁智深




如何修改机构体内部的数组

#include<stdio.h>#include<stdlib.h>#include<string.h>structstr{charbuf[100];};voidfun1(structstrs){strcpy(s.buf,"hello");}voidfun2(chars[]){strcpy(s,"hello");}intmain(){structstrs={"world!"};;fun1(s);//传结构体,相当于赋值过去了,不会改变变量(会很消耗内存的性能)printf("%s\n",s.buf);chars1[100]="world!";fun2(s1);//数组会把地址传过去,会修改变量printf("%s\n",s1);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outworld!hello








结构体函数 初始化结构体

#include<stdio.h>#include<stdlib.h>#include<string.h>structstr{charbuf[100];};structstrgetstr(){structstrs;strcpy(s.buf,"HelloWorld!");returns;}char*getstr1(){charbuf[100];//在栈区strcpy(buf,"HelloWorld!");//returnbuf;//无法返回有效数据}intmain(){//char*tmp=getstr1();非法执行structstrtmp=getstr();printf("%s\n",tmp.buf);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outHelloWorld!




【指向结构体的指针】


返回结构体,消耗很大

#include<stdio.h>#include<stdlib.h>#include<string.h>structstr{charbuf[100];};structstrgetstr(){structstrs;strcpy(s.buf,"HelloWorld!");returns;}char*getstr1(){charbuf[100];//在栈区strcpy(buf,"HelloWorld!");//returnbuf;//无法返回有效数据}intmain(){//char*tmp=getstr1();非法执行structstrtmp=getstr();//内存拷贝,消耗很大printf("%s\n",tmp.buf);return0;}





返回结构体指针,消耗很小

#include<stdio.h>#include<stdlib.h>#include<string.h>structstr{charbuf[100];};structstr*getstr(){structstr*s=malloc(sizeof(structstr));printf("%p\n",s);strcpy(s->buf,"HelloWorld!");returns;//把指针返回去}intmain(){structstr*tmp=getstr();//内存拷贝,消耗很大printf("%p\n",tmp);printf("%s\n",tmp->buf);free(tmp);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out0x8cc0100x8cc010HelloWorld!





联合体初步1

#include<stdio.h>#include<stdlib.h>#include<string.h>unionvar{charc;inti;shortd;char*s;//很危险};structstr{charc;inti;shortd;};intmain(){/*结构体与联合体元素地址区别*/unionvarv;//联合体元素公用用一个地址printf("%p\n",&(v.c));printf("%p\n",&(v.i));printf("%p\n",&(v.d));//小端对齐,高位放高位,低位放低位structstrs;//结构体,元素分别独立printf("%p\n",&(s.c));printf("%p\n",&(s.i));printf("%p\n",&(s.d));/*修改联合体元素*/printf("%ld\n",sizeof(v));v.c=100;printf("%d\n",v.c);v.i=1;printf("%d\n",v.c);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out0x7ffc3f56e5d00x7ffc3f56e5d00x7ffc3f56e5d00x7ffc3f56e5e00x7ffc3f56e5e40x7ffc3f56e5e881001




枚举

#include<stdio.h>#include<stdlib.h>#include<string.h>enumspectrum{red,yellow,green,blue,white,black};//申明一个枚举enumnumber{zero=10,one=9,two,three};//申明一个枚举voidtest(inti){printf("test\n");}voidtest1(inta,intb){printf("test1\n");}voidtest2(inta,intb,intc){printf("test2\n");}void*function_factory(enumnumbern){if(n==zero)returntest;if(n==one)returntest1;if(n==two)returntest2;}voidgetcolor(enumspectrumcolor){if(color==red)printf("red\n");if(color==yellow)printf("yellow\n");if(color==green)printf("green\n");if(color==blue)printf("blue\n");}intmain(){enumnumberb=one;void*p=function_factory(b);printf("%p,%p\n",p,test1);enumspectrumcolor=red;getcolor(color);printf("%d,%d,%d\n",red,yellow,green);printf("%d,%d,%d\n",zero,one,two);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out0x400594,0x400594red0,1,210,9,10



typedef 初步

#include<stdio.h>#include<stdlib.h>#include<string.h>typedefunsignedcharBYTE;#definemybyteunsignedchartypedefunsignedintUINT;//严格检查变量类型#defineMAX100//简单替换,不做变量类型检查,没有分号structstudent{intid;charname[100];};intmain(){BYTEb1=0xff;printf("%x\n",b1);UINTu1=0xFF00FF00;printf("%x\n",u1);//正常使用structstudentstudent1;//typedef来定义typedefstructstudentSTUDENT;//自定义数据类型STUDENTstudent2;return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outffff00ff00




没有用typedef之前的代码,看着很晕

#include<stdio.h>#include<stdlib.h>#include<string.h>constchar*func1(constchar*str1,constchar*str2){char*p=malloc(strlen(str1)+strlen(str2)+1);strcpy(p,str1);strcat(p,str2);returnp;}constchar*func2(constchar*(*p)(constchar*str1,constchar*str2),constchar*s1,constchar*s2){returnp(s1,s2);}intmain(){constchar*tmp1="Hello";constchar*tmp2="world!";constchar*s=func2(func1,tmp1,tmp2);printf("%s\n",s);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outHelloworld!



typedef优化 对比

#include<stdio.h>#include<stdlib.h>#include<string.h>//定义一个指向这种函数类型的指针typedefconstchar*(*FUNC1)(constchar*str1,constchar*str2);constchar*func1(constchar*str1,constchar*str2){char*p=malloc(strlen(str1)+strlen(str2)+1);strcpy(p,str1);strcat(p,str2);returnp;}constchar*func2(FUNC1p,constchar*s1,constchar*s2){returnp(s1,s2);}intmain(){constchar*tmp1="Hello";constchar*tmp2="world!";constchar*s=func2(func1,tmp1,tmp2);printf("%s\n",s);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outHelloworld!




typedef深入1

#include<stdio.h>#include<stdlib.h>#include<string.h>//定义一个指向这种函数类型的指针的数据类型typedefconstchar*(*FUNC1)(constchar*str1,constchar*str2);//这是函数的原始申明constchar*func1(constchar*str1,constchar*str2){char*p=malloc(strlen(str1)+strlen(str2)+1);strcpy(p,str1);strcat(p,str2);returnp;}constchar*func2(FUNC1p,constchar*s1,constchar*s2){returnp(s1,s2);}FUNC1test(){FUNC1tmp=func1;returntmp;}intmain(){//定义10个FUNC1数据类型FUNC1f[10];//定义一个数组10个元素,参数是constchar*str1,constchar*str2,返回值是constchar*constchar*(*p[10])(constchar*str1,constchar*str2);constchar*tmp1="Hello";constchar*tmp2="world!";constchar*s=func2(func1,tmp1,tmp2);printf("%s\n",s);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outHelloworld!



超级复杂的typedef

chunli@ubuntu:~/pointer$catmain.c#include<stdio.h>#include<stdlib.h>#include<string.h>typedefunsignedcharBYTE;typedefunsignedintUINT;#defineMYBYTEunsignedchar#defineMAX100//typedef100MYMAX;structstudent{intID;charname[MAX];};typedefstructstudentSTUDENT;typedefconstchar*(*FUNC1)(constchar*str1,constchar*str2);constchar*func1(constchar*str1,constchar*str2){char*p=malloc(strlen(str1)+strlen(str2)+1);strcpy(p,str1);strcat(p,str2);returnp;}/*constchar*(*)(constchar*str1,constchar*str2)test(){FUNC1tmp=func1;returntmp;}*/constchar*func2(constchar*(*p[])(constchar*str1,constchar*str2),constchar*s1,constchar*s2){return(p[0])(s1,s2);}intmain(){FUNC1f[10];//constchar*tmp1="hello";constchar*tmp2="world";f[0]=func1;constchar*s=func2(f,tmp1,tmp2);printf("s=%s\n",s);BYTEb;b=0x12;UINTi;i=0xffff;STUDENTst;return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outs=helloworldchunli@ubuntu:~/pointer$




【复习================================】


联合体的指针,很危险

#include<stdio.h>#include<stdlib.h>#include<string.h>unionvar{charc;inti;shortd;char*s;//很危险};intmain(){unionvarv;v.s=(char*)malloc(100);v.c=1;free(v.s);//致命错误!return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.outSegmentationfault(coredumped)



typedef 特别高级的用法

chunli@ubuntu:~/pointer$catmain.c#include<stdio.h>#include<stdlib.h>#include<string.h>typedefstructstudentST;structstudent{charname[200];intid;};typedefconstchar*(*FUNC1)(constchar*str1,constchar*str2);constchar*funcl(constchar*str1,constchar*str2){printf("%s,%s\n",str1,str2);returnNULL;}constchar*func2(FUNC1p,constchar*str1,constchar*str2){returnp(str1,str2);}intmain(){STstudent1;strcpy(student1.name,"奥巴马");student1.id=1;printf("%d,%s\n",student1.id,student1.name);return0;}chunli@ubuntu:~/pointer$gcc-std=c99main.c&&./a.out1,奥巴马




不使用typedef



使用typedef