一、 结构体类型指针
1、结构体指针变量
以读方式访问形参的函数,仅出于性能的考虑,可以地址方式传参,避免结构复制所带来的开销。
为防止在函数中意外地修改实参,可以用常量指针定义参数。
2、指针引用结构体成员的三种形式
①结构体变量名.成员名
②(*p).成员名
③p- >成员名
p->n //得到p指向的结构体变量中的成员n的值
p->n++ //先用p指向的结构体变量的成员n的值,用完后该成员n值加1;
++p->n //成员n值先加1,然后使用n
二、 指向结构体变量的结构体指针变量
1、结构体指针变量的指向和输出
结构体变量的指针是该结构体变量所占据内存段的起始地址。
例1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main(int argc,char const *argv[])
{
struct stu
{
int x;
float y;
char a[4];
}ww,*p;
p=&ww;//指针指向结构体变量ww
ww.x=10;
ww.y=20;
strcpy(ww.a,"abc");
printf("%d\n",*p); //10
printf("%f\n",(*p).y); //20.000000
printf("%s\n",p->a); //abc
printf("%c\n",p->a[0]); //a
while(1);
return 0;
}
例2:
#include <stdio.h>
typedef struct date
{
int year;//年
int month;//月
int day;//日
}DATE;//定义struct date类型,别名为DATE,有3个成员
struct student//st->birthday.year
{
char name[128];//姓名
int age;//年龄
DATE birthday;//出生时间
}s1={"小云",21,{1996,9,21}};//s1是结构体Student的变量。
typedef struct student STU;
void show(const STU *st)
{
printf("姓名:%s\n",st->name);
printf("年龄:%d\n",st->age);
printf("生日:%d年%d月%d日\n",st->birthday.year,
st->birthday.month,st->birthday.day);
}
void grow(STU *st)//更改年龄
{
st->age++;
}
void main()
{
STU s2={"小舞",18,{1996,10,5}};
STU *ps=&s2;//结构体指针指向结构体变量
STU *pt;//定义结构体变量,未初始化,未指向结构体变量
grow(&s2);
printf("%d %d\n",ps->age,ps->birthday.year);
show(&s2);
printf("%s\n",s1.name);
pt=&s1;
show(pt);
}
例3:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char const *argv[])
{
struct student
{
long int num;
char name[20];
char sex;
};
struct student stu_1;
struct student *p;
p=&stu_1;//指针指向结构体
stu_1.num=9901;
strcpy(stu_1.name,"Li Min");
stu_1.sex='M';
printf("No:%ld name:%s sex:%c \n",stu_1.num,stu_1.name,stu_1.sex);
printf("No:%ld name:%s sex:%c \n",(*p).num,(*p).name,(*p).sex);
printf("No:%ld name:%s sex:%c \n",p->num,p->name,p->sex);
while(1);
return 0;
}
//输出:
//No:9901 name:Li Min sex:M
//No:9901 name:Li Min sex:M
//No:9901 name:Li Min sex:M
2、结构体指针变量作为形参
用指向结构体类型数据的指针作为函数的参数-把结构体变量的值由一个函数传递给另一个函数。
(1)用结构体的成员作为函数参数。把结构体成员的数值传给形参。(单向值传递)
(2)用结构体变量作为函数参数,把整个结构体变量传给形参。(单向值传递)
(3)用指向结构体变量的指针作为实参,将结构体变量的地址传给形参。(双向地址传递)
例1:
#define FORMAT "%d\n%s\n%f\n%f\n%f\n"
struct student
{
int num;
char name[20];
float score[3];
}stu={12345,"Li li",67.5,89,78.6};
int main(int argc,char const *argv[])
{
void print(struct student *);//函数声明
print(&stu); //实参是结构体变量的地址
while(1);
return 0;
}
void print(struct student *p) //形参是指向结构体变量的指针变量
{
printf(FORMAT,p->num,(*p).name,(*p).score[0],p->score[1],p->score[2]);
}
三、 指向结构体数组的结构体指针变量
结构体数组的元素可以用指针或指针变量来指向、进行引用。
例1:
#include <stdio.h>
#include <stdlib.h>
struct student
{
int num;
char name[20];
char sex;
int age;
};
struct student stu[3]={
{10101,"LiLin",'M',18},
{10102,"ZhangHua",'M',19},
{10103,"WangPin",'F',20}
};
int main(int argc,char const *argv[])
{
struct student *p;
printf(" NO: Name Sex Age\n");
for(p=stu;p<stu+3;p++)
{
printf("%5d %8s %2c %d\n",p->num,(*p).name,p->sex,(*p).age);
}
while(1);
return 0;
}
p定义为结构体student的指针变量,则p++ 指向的是结构体数组的下一个元素,而不是结构体的下一个成员。由于定义的是指向结构体的指针,因此它只能指向结构体,而不能指向结构体的成员。如果一定要指向一个非结构体数据,则可以使用强制类型转换。
如:
p=(struct student *)&stu[0].age;
//把stu[0].age成员的地址强制转换成struct student 类型并赋值给p
例2:
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
char name[10];
int ino;
int age;
}STU_T;
void print(STU_T *p,int len)
{
STU_T *p2;
printf("%d\n",len);//4
for(p2=p;p2<p+len;p2++)
{
printf("%s,%d,%d\n",p2->name,p2->ino,p2->age);
//admin1,1001,15 admin2,1002,16 admin3,1003,17 admin4,1004,18
}
}
void main()
{
int len=0;
STU_T stu1={"admin",1000,15};
STU_T stus[4]={
{"admin1",1001,15},
{"admin2",1002,16},
{"admin3",1003,17},
{"admin4",1004,18}
};
STU_T *p=NULL;
p=&stu1;
len=sizeof(stus)/sizeof(stus[1]);
print(stus,len);
printf("%s,%d,%d\n",stu1.name,stu1.ino,stu1.age);//admin,1000,15
printf("%s,%d,%d\n",p->name,p->ino,p->age);//admin,1000,15
printf("%s,%d,%d\n",stu1.name,(*p).ino,p->age);
while(1);
return 0;
}
例3:
#include <stdio.h>
#include <stdlib.h>//malloc的头文件
#include <string.h>
struct student
{
int id;
int score;
char name[128];
void (*printfo)(int,char*,int); //定义函数指针
};
void printfoReal(int id,char *name,int score)//输出结构体信息
{
printf("我的姓名:%s,学号:%d,成绩:%d\n",name,id,score);
}
void initStus(struct student stus[],int total)
{
int i;
//2.一个一个输入学生信息
for(i=0;i<total;i++)//赋值
{
printf("请输入第%d学生的学号: ",i+1);
scanf("%d",&(stus[i].id));
printf("请输入第%d学生的姓名: ",i+1);
scanf("%s",stus[i].name);
printf("请输入第%d学生的成绩: ",i+1);
scanf("%d",&(stus[i].score));
stus[i].printfo=printfoReal;//结构体中函数指针指向具体函数
}
}
void findDatas(struct student stus[],int total,struct student *pbest,struct student *pworst)
{
//3.查找最高分,最低分
int i;
*pbest=*pworst=stus[0];
for(i=0;i<total;i++)
{
if((*pbest).score<stus[i].score)
{
*pbest=stus[i];
}
if(pworst->score>stus[i].score)
{
*pworst=stus[i];
}
}
}
void putStus(struct student stus[],int total)
{
int i;
//4.输出结果
for(i=0;i<total;i++)//调用输出函数
{
stus[i].printfo(stus[i].id,stus[i].name,stus[i].score);
//调用函数指针指向的函数
}
}
int main(int argc,char const *argv[])
{
int i;
int total=3;
struct student best;
struct student worst;
struct student stus[10];
#if 0
//1.要求输入总人数
printf("请输入班级总人数: ");
//linux下可如此写,window下变量需写在最前面
scanf("%d",&total);
struct Student stus[total];
#endif
initStus(stus,total);//初始化
putStus(stus,total);//输出各成员信息
findDatas(stus,total,&best,&worst);//查找出最大值和最小值
printf("最高成绩\n");
best.printfo(best.id,best.name,best.score);//输出最大值
printf("最低成绩\n");
worst.printfo(worst.id,worst.name,worst.score);//输出最小值
while(1);
return 0;
}
例4:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
int id;
int score;
char *name;
void (*printfo)(int,char*,int);//定义函数指针
};
void printfoReal(int id,char *name,int score)
{
printf("我的姓名:%s,学号:%d,成绩:%d\n",name,id,score);
}
void initStus(struct student *stus,int total)
{
int i;
//2.一个一个输入学生信息
for(i=0;i<total;i++)
{
printf("请输入第%d学生的学号: ",i+1);
scanf("%d",&(stus->id));
printf("请输入第%d学生的姓名: ",i+1);
stus->name=(char *)malloc(128);//开辟空间
scanf("%s",stus->name);
printf("请输入第%d学生的成绩:",i+1);
scanf("%d",&((*stus).score));
stus->printfo=printfoReal;//结构体中函数指针指向具体函数
stus++;
}
}
void findDatas(struct student *pstus,int total,struct student *pbest,struct student *pworst)
{
int i;
//3.查找最高分,最低分
*pbest=*pworst=*pstus;
for(i=0;i<total;i++)
{
if((*pbest).score<pstus->score)
{
*pbest=*pstus;
}
if(pworst->score>pstus->score)
{
*pworst=*pstus;
}
pstus++;
}
}
void putStus(struct student *pstus,int total)//调用输出函数
{
int i;
//4.输出结果
for(i=0;i<total;i++)//调用输出函数
{
pstus->printfo(pstus->id,pstus->name,pstus->score);
pstus++;
}
}
int main(int argc,char const *argv[])
{
int total=3;
struct student best;
struct student worst;
struct student stus[10];
#if 0
//1.要求输入总人数
printf("请输入班级总人数: ");
//linux下可如此写,window下变量需写在最前面
scanf("%d",&total);
struct student stus[total];
#endif
initStus(stus,total);//初始化
putStus(stus,total);//输出各成员信息
findDatas(stus,total,&best,&worst);//查找出最大值和最小值
printf("最高成绩\n");
best.printfo(best.id,best.name,best.score);//输出最大值
printf("最低成绩\n");
worst.printfo(worst.id,worst.name,worst.score);//输出最小值
while(1);
return 0;
}
四、指向结构体类型函数的结构体指针变量(结构体类型指针作为返回值)
例1:
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
char name[10];
int ino;
int age;
}STU_T;
STU_T *get()
{
static STU_T stus[3]={
{"admin1",1000,15},
{"admin2",1001,16},
{"admin4",1004,18}
};
return &stus[1];//返回值(指针)
}
void main()
{
int len=0;
STU_T stus[3]={0};//定义定初始化为0
STU_T *p=NULL;
len=sizeof(stus)/sizeof(stus[1]);
p=get();
printf("%s %d %d\n",p->name,(*p).ino,p->age);//admin2 1001 16
}
五、动态分配内存的结构体指针变量
例1:
#include <stdio.h>
#include <stdlib.h>//malloc的头文件
#include <string.h>
struct student
{
int id;
int score;
char name[128];
void (*printfo)(int,char*,int);//定义函数指针
};
void printfoReal(int id,char *name,int score)
{
printf("我的姓名:%s,学号:%d,成绩:%d\n",name,id,score);
}
int main(int argc,char const *argv[])
{
struct student stu1;
struct student *stu2;
stu2=(struct student *)malloc(sizeof(struct student));//开辟空间
stu1.id=10;
stu1.score=85;
strcpy(stu1.name,"lili");
stu1.printfo=printfoReal;//结构体中函数指针指向具体函数
stu2->id=11;
stu2->score=86;
strcpy(stu2->name,"lily");
stu2->printfo=printfoReal;//结构体中函数指针指向具体函数
stu1.printfo(stu1.id,stu1.name,stu1.score); //调用函数指针指向的函数
stu2->printfo(stu2->id,stu2->name,(*stu2).score); //调用函数指针指向的函数
while(1);
return 0;
}
编辑 2020-06-16 12:30 首次编辑
增改 2021-07-22 23:47 内容结构修改
注:本文旨于作为自己的学习笔记,不作他用。