.net给网站做短信验证,广州网站建设设计公司,公众号开发者权限哪里添加,html教程菜鸟教程下载为什么要用结构体#xff1f; 在实际问题中#xff0c;一组数据往往具有不同的数据类型。例如#xff0c;在学生登记表中#xff0c;姓名应为字符型;学号可为整型或字符型#xff1b;年龄应为整型#xff1b;性别应为字符型#xff1b;成绩可为整型或实型。显然不能用一…为什么要用结构体 在实际问题中一组数据往往具有不同的数据类型。例如在学生登记表中姓名应为字符型;学号可为整型或字符型年龄应为整型性别应为字符型成绩可为整型或实型。显然不能用一个数组来存放这一组数据。因为数组中各元素的类型和长度都必须一致以便于编译系统处理。为了解决这个问题语言中给出了另一种构造数据类型——“结构structure”或叫“结构体”。 它相当于其它高级语言中的记录。“结构”是一种构造类型它是由若干“成员”组成的。每一个成员可以是一个基本数据类型或者又是一个构造类型。结构既是一种“构造”而成的数据类型那么在说明和使用之前必须先定义它也就是构造它。如同在说明和调用函数之前要先定义函数一样。让编程序的人自定义一个数据类型。
结构体的定义
struct Datas //结构体的定义用关键字struct模板的作用
{int a;char c;float f;char*p;int array[2];
};结构体的使用一
#include stdio.h
#include stdlib.h
struct Student //结构体的定义用关键字struct模板的作用相当于自定义的类型
{int score; //特征分数char name[128];//特征名字,这个是定义了可以存储128个字节大小的数组,空格占一个字节void (*pintroduce)(char* pname);//这里是函数指针
};
int main()
{//结构体的使用://类型 变量名 初始值struct Student stu1 {98,feng nan nan};//如何访问结构体printf(结构体中的score%d\n,stu1.score);printf(结构体中的name%s\n,stu1.name);struct Student stu2;stu2.score99;/*stu2.name冯楠楠 在给结构体中的字符串赋值时C、java可以这样写C语言必须用字符串拷贝函数strcpy进行赋值*/char* str冯楠楠;strcpy(stu2.name,str);printf(结构体中的score%d\n,stu2.score);printf(结构体中的name%s\n,stu2.name);system(pause);return 0;
}结构体使用二
#include stdio.h
#include stdlib.hvoid func(int data)
{printf(函数data%d\n,data);
}
struct Datas
{char*p1;//这里p1是指针int a;char c;float f;double d;char str[128];void (*p)(int a);
};
int main()
{/*char *strhello;这样写可以char str[];strhello!;这样写就不行了要写为strcpy(str,hello!);还可以这样写char *strNULl;//定义指针时不往指针里写东西就不用NULL//如果要是写还要malloc并且memsetstrhello!;//可以直接赋值但最好都加*/char* str1NULL;//定义一个指针没有malloc不能往里面写东西str1(char*)malloc(128);memset(str1,\0,128);strcpy(str1,hello!);char str[]你很帅;struct Datas d1;d1.a100;d1.cd;d1.f3.14;d1.d123.2323;strcpy(d1.str,str);d1.pfunc;d1.p1(char*)malloc(128);//p1在结构体中没有开辟空间是个野指针不能指直接写入需要开辟空间memset(d1.p1,\0,128);strcpy(d1.p1,注意指针这是否开辟空间);printf(结构体输出%d\n,d1.a);printf(结构体输出%c\n,d1.c);printf(结构体输出%f\n,d1.f);printf(结构体输出%lf\n,d1.d);puts(d1.str);puts(d1.p1);d1.p(10);//结构体函数调用system(pause);return 0;
}结构体数组
#include stdio.h
#include stdlib.hstruct Student
{int score;char *name;//这里尽量用指针减小结构体的大小//结构体太大传参数占空间
};
int main()
{int i;struct Student stu[3];struct Student maxStudent;//找最高分最低分找的是人也就是详细的信息用结构体struct Student minStudent; for(i0;isizeof(stu)/sizeof(stu[0]);i){printf(请输入第%d个学生的名字\n,i1);stu[i].name(char*)malloc(128);scanf(%s,stu[i].name);//注意结构体内的指针使用前要开辟空间printf(请输入第%d个学生的分数\n,i1);scanf(%d,stu[i].score); }for(i0;isizeof(stu)/sizeof(stu[0]);i){printf(%s:%d\n,stu[i].name,stu[i].score);}//maxStudent.scorestu[0].score;//minStudent.scorestu[0].score;minStudentmaxStudentstu[0];//相同类型的结构体可以对等for(i0;isizeof(stu)/sizeof(stu[0]);i){if(maxStudent.scorestu[i].score)maxStudentstu[i];if(minStudent.scorestu[i].score)minStudentstu[i];}printf(最高分是%s:%d\n最低分是%s:%d\n,maxStudent.name,maxStudent.score,minStudent.name,minStudent.score);system(pause);return 0;
}结构体指针
#include stdio.h
#include stdlib.h
//1、如果用结构体指针就不能用点运算符访问结构体中的变量应该用-
//2、注意结构体指针是否是野指针或者NULL若是则会出现段错误
struct Student
{int score;char name[128];
};
int main()
{struct Student stu1;stu1.score100;strcpy(stu1.name,冯楠楠);printf(姓名:%s\n分数:%d\n,stu1.name,stu1.score);int* a;//整型定义指针struct Student *pNULL;//同样的道理也可以定义结构体指针//这里这样定义属于野指针,对野指针进行写操作要出现段错误p(struct Student*)malloc(sizeof(struct Student));//不管是野指针还是等于NULL,//都不能对这个非法的内存访问,否则出现段错误 p-score150;//如果用结构体指针就不能用点运算符访问结构体中的变量要用-strcpy(p-name,冯楠楠);printf(姓名:%s\n分数:%d\n,p-name,p-score);free(p);//空间不用了就free掉防止内存泄漏pstu1;//指针是存放地址的变量之前指向malloc那片空间现在存放的是stu1的地址printf(姓名:%s\n分数:%d\n,p-name,p-score); printf(地址是%p\n,p);//因为结构体大小为1284132所以指针偏移132个字节(十进制)结果0060FE68printf(加加后地址是%p\n,p);//结果0060FEEC/*总结来说指针要看指针指向的对象是谁并不是1*/system(pause);return 0;
}结构体指针操作学生成绩表
#include stdio.h
#include stdlib.h
/*
结构体指针访问结构体内部元素方法
结构体指针 -成员名如addr-country;
(*结构体指针).成员名(*addr).country;//很少去进行使用注意必须去使用(),因为.优先级大于*
*/
struct Student
{int score;char*name;//4,linux 8
};
int main()
{int i;int len2;struct Student stu[2];struct Student *pstu;//结构体指针指向数组的头其实和整型数是一样的for(i0;isizeof(stu)/sizeof(stu[0]);i){printf(请输入名字\n);p-name(struct Student*)malloc(128);scanf(%s,p-name);printf(请输入分数\n);scanf(%d,(p-score));p;}pstu;for(i0;isizeof(stu)/sizeof(stu[0]);i){printf(姓名%s 分数%d\n,p-name,p-score);p;}struct Student *p2(struct Student *)malloc(len*sizeof(struct Student));//上一行代码是直接定义了结构体指针并给他开辟5*sizeof(struct Student)怎么大的空间//相当于有5个结构体数组,可以存储5个人的信息for(i0;ilen;i){printf(请输入名字\n);p2-name(struct Student*)malloc(128);scanf(%s,p2-name);printf(请输入分数\n);scanf(%d,(p2-score));p2;}p2-len;for(i0;ilen;i){printf(姓名%s 分数%d\n,p2-name,p2-score);p2;}system(pause);return 0;
}结构体指针函数综合处理学生成绩
#include stdio.h
#include stdlib.h
//malloc在堆上面开辟空间函数调用结束后空间不会被释放
struct Student
{int score;char* name;
};
struct Student* initStuScores(int* len)//初始化函数获取用户输入完成初始化
{int i;printf(请输入总人数\n);scanf(%d,len);struct Student *p2(struct Student *)malloc((*len)*sizeof(struct Student));//上一行代码是直接定义了结构体指针并给他开辟5*sizeof(struct Student)怎么大的空间//相当于有5个结构体数组,可以存储5个人的信息//malloc开辟的空间不会消失在函数内部定义的指针变量不会对main函数中的指针有影响//p2是局部变量返回的是p2的内容不是p2for(i0;i(*len);i){printf(请输入名字\n);p2-name(struct Student*)malloc(128);scanf(%s,p2-name);printf(请输入分数\n);scanf(%d,(p2-score));p2;}return p2-*len;
}
void printMes(struct Student* p2,int len)
{int i;for(i0;ilen;i){printf(姓名%s 分数%d\n,p2-name,p2-score);p2;}//p2p2-len;
}
struct Student* findMaxStu(struct Student* p,int len)
{int i0;struct Student* maxStudent;maxStudentp;for(i;ilen;i){if((p-score)(maxStudent-score)){maxStudentp;}p;}return maxStudent;
}
struct Student* findMinStu(struct Student* p,int len)
{int i0;struct Student* minStudent;minStudentp;for(i;ilen;i){if((p-score)(minStudent-score)){minStudentp;}p;}return minStudent;}
float getAverage(struct Student*p,int len)
{int i;float toal0;for(i0;ilen;i){toaltoalp-score;p;}return (float)toal/len;
}
int findSome(struct Student*p,int len,char*name)
{int i;for(i0;ilen;i){if(strcmp(name,p-name)0){return 1;}p;}return -1;
}
int main()
{int len;struct Student *pstusinitStuScores(len);printMes(pstus,len);struct Student* maxNULL;struct Student* minNULL;maxfindMaxStu(pstus,len);minfindMinStu(pstus,len);//函数传参其实就是将地址值拷贝一份给函数//函数内的指针变量不会对main函数中的指针有影响//除非用二级指针printf(最高分%d姓名%s\n,max-score,max-name);printf(最低分%d姓名%s\n,min-score,min-name);printf(平均分是:%f\n,getAverage(pstus,len));if(findSome(pstus,len,冯楠)1){printf(找到此人\n);}else{printf(没有此人\n);}system(pause);return 0;
}结构体大小如何计算
#include stdio.h
#include stdlib.h
/*由于存储变量地址对齐的问题结构体大小计算必须满足两条原则一、结构体成员的偏移量必须是成员大小的整数倍0被认为是任何数的整数倍二、结构体大小必须是所有成员数组和结构体除外大小的整数倍三、对齐方式确实很浪费空间可是按照计算机的访问方式这种对齐方式提高了效率*/
//简单结构体
struct s1
{char ch1;//1 ch1相对于整个结构体的偏移量就是0因为他是结构体的第一项char ch2;//1 ch2相对于整个结构体的偏移量就是1因为结构体第一项是1个字节int i;//4 i相对于整个结构体的偏移量就是2,2不是4的倍数逻辑偏移2//实际按照对齐规则要偏移4个字节,这样ch2和i之间就右空余了两个字节//所以一共是8个字节
};
//简单结构体
struct s2{char ch1;//1 ch1偏移量是0,int i;//4 i的逻辑偏移值是1要满足第一条规则所以偏移4//这样ch1和i之间就有3个字节char ch2;//1 逻辑偏移量是8满足条件一但是结构体总大小为九//不满足条件二所以ch2要向后偏移3个字节所以总大小是12
};
//成员包含数组的结构体
struct s3{char ch;//偏移值1int i;// 逻辑偏移值是1实际偏移值4ch和i之间有三个字节char str[10];//逻辑偏移值8实际偏移值10所以总大小是20//这个char类型的数组只需要把它看做十个char连在一起即可
};
//成员包含结构体的结构体,若结构体内的结构体仅仅是声明不占空间则可忽略
struct s4{char ch;//偏移量是1int i;//实际偏移量是1348struct s{char ch1;int j;};//这个结构体大小是8但是没有定义所以忽略float f;//逻辑偏移量是8实际偏移量是8所以整个结构体大小为8412//满足条件一二
};
//成员包含结构体的结构体,若结构体内的结构体有定义则占空间要计算
struct s5{char ch;//偏移量是1int i;//实际偏移量是1348struct ss{char ch1;int j;}stemp;//这个结构体大小是8满足条件一float f;//逻辑偏移量是16实际偏移量是16所以整个结构体大小为16420//满足条件一二
};
//成员包含联合体的结构体
struct s6{char ch;int i;union{//联合体按照最大的计算就是4char ch1;int j;};
};
//指定对齐值:对齐值小于最大类型成员值
//如果最大成员超过了pack的要求就按pack来对齐
//如果最大成员没有超过pack结构体总大小按最大成员开对齐
#pragma pack(4) //指定向4对齐 最大是8
struct s7{char ch;int i;float f;double d;
};
//对齐值大于最大类型成员值,当指定对齐值大于自身对齐值时向自身对其值对齐大小是24.#pragma pack(10)
struct s8{char ch;int i;float f;double d;
};
int main()
{printf(char:%d\n,sizeof(char));//1printf(float:%d\n,sizeof(float));//4printf(int:%d\n,sizeof(int));//4printf(double:%d\n,sizeof(double));//8printf(s1:%d\n,sizeof(struct s1));//8printf(s2:%d\n,sizeof(struct s2));//12printf(s3:%d\n,sizeof(struct s3));//20printf(s4:%d\n,sizeof(struct s4));//12printf(s5:%d\n,sizeof(struct s5));//20printf(s6:%d\n,sizeof(struct s6));//12printf(s7:%d\n,sizeof(struct s7));//20printf(s8:%d\n,sizeof(struct s8));//24system(pause);return 0;
}typedef关键字
#include stdio.h
#include stdlib.h
/*typedeftypedef关键字作用是为一种数据类型定义一个新的名字这里的数据类型包括int、char等等和自定义的数据类型struct等
*//*在单片机开发中寄存器有8位 16位 32位int data0x1234;int是4个字节32位如果是8位单片机的话可能装不下所以有了 char data0x11这样的定义因为数据类型的表示范围都是有重合的地方的比如0~128 int float double char 这四个数据类型都表示但是char表示数字就有了以下的写法typedef unsigned char u_int8;表示0~255这个区间的数typedef unsigned short int u_int16;typedef unsigned short int u_int32;这样定以后就可以用u_int8来代替unsigned charu_int16 nsigned shortu_int32 unsigned short然后就可以:u_int8 data10;u_int16 data220u_int32 data330;这种定义方式了
*//*
typedef struct Student
{int score;char* name;void (*p)(struct Student stu1);//定义一个函数指针要求参数类型是结构体类型的//可以用struct Student但是不可以用STU stu1 //因为STU定义在结构体外边
}STU,*PSTU;//通常使用typedef重命名结构体时会命名名称和指针
*/
/*
typedef struct Student STU,*PSTU;也可以这样重命名结构体
*/
typedef struct//也可以将Student去掉直接给结构体命名
{int score;char* name;void (*p)(struct stu);
}STU,*PSTU;//通常使用typedef重命名结构体时会命名名称和指针int main()
{STU stu1;//直接可以用命名后的STU代替struct Studentstu1.score100;printf(%d\n,stu1.score);PSTU stu2;//这个stu2就代表结构体指针这行代码等同于struct Student* stu2//PSTU就等同于struct Student*stu2(PSTU)malloc(sizeof(STU));stu2-score99;printf(%d\n,stu2-score);system(pause);return 0;
}