一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量.用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。
1指向结构体变量的指针
下面通过一个简单例子来说明指向结构体变量的指针变量的应用。
例11.3指向结构体变量的指针的应用。
# include <string. h>
main ( )
{struct student
{long num;
char name[20];
char sex;
float score;
};
struct student stu_1;
struct student* p;
p=&stu_1;
stu_1.num=89101;
strcpy(stu_1. name,"Li Lin" );
stu_1.sex='M' ;
stu_1.score=89.5;
printf ("No. :%ld\nname:%s\nsex:%c \nscore:%f\n",stu_1. num,stu_ 1. name, stu_ 1. sex,
stu-1.score);
printf ("No. :%ld\nname:%s\nsex:%c\nscore:%f\n",( * p).num,( * p). name,( *p),sex,
(*p).score);
在主函数中声明了struct student类型,然后定义一个struct student类型的变量 stu-1。同时又定义一个指针变量p,它指向一个 struct student类型的数据。在函数的执行部分将结构体变量stu_1的起始地址赋给指针变量p,也就是使p指向stu-1(见图11.7),然后对stu_1的各成员赋值。第一个printf函数是输出stu_1的各个成员的值。用stu_1.num表示stu-1中的成员num,余类推。第二个printf函数也是用来输出stu-1各成员的值,但使用的是(*p).num 这样的形式。(*p)表示p指向的结构体变量,(*p).num 是p指向的结构体变量中的成员num。注意*p两侧的括弧不可省,因为成员运算符“.”优先于“*”运算符,*p.num 就等价于*(p.num)了。
程序运行结果如下:
No:89101
name:Li Lin
sex:M
score:89.500000
No:89101
name;Li Lin
sex:M
score:89.500000
可见两个printf函数输出的结果是相同的。
在C语言中,为了使用方便和使之直观,可以把(*p).num 改用p->num 来代替,它表示p所指向的结构体变量中的num成员。同样,(*p).name 等价于p-> name。也就是说,以下三种形式等价:
- 结构体变量.成员名
- (*p).成员名
- p->成员名
上面程序中最后一个printf函数中的输出项表列可以改写为
p->num,p->name,p->sex,p->score
其中一>称为指向运算符。
请分析以下几种运算:
p->n 得到p指向的结构体变量中的成员n的值。
p->n++ 得到p指向的结构体变量中的成员n的值,用完该值后使它加1。
++p->n 得到p指向的结构体变量中的成员n的值加1,然后再使用它。
2指向结构体数组的指针
以前已经介绍过,可以使用指向数组或数组元素的指针和指针变量。同样,对结构体数组及其元素也可以用指针或指针变量来指向。
例11.4指向结构体数组的指针的应用。
struct student
{int num;
char name[20];
char sex;
int age;
}
struct student stu[3]={{10101."Li Lin",'M',18},(10102,"Zhang Fun",' M',19}.{10104,
"Wang Min",'F’,20}}:
main()
{struct student *p;
printf(" No. Name sex age\n");
for (p=stu;p<stu+3;p++)
printf ("%5d %-20s %2c %4d\n",p->num,p->name,p->sex,p->age);
}
运行结果如下:
p是指向 struct student结构体类型数据的指针变量。在for语句中先使p的初值为stu,也就是数组stu 的起始地址,见图11.8中p的指向。在第一次循环中输出stu[0]的各个成员值。然后执行p++,使p自加1.p加1意味着p所增加的值为结构体数组stu的一个元素所占的字节数(在本例中为2+20+1+2=25 字节)。执行p++后p的值等于stu+1,p指向stu[1]的起始地址,见图11.8中p'的指向。在第二次循环中输出stu[1]的各成员值。在执行p++后.p的值等于stu+2,它的指向见图10.8中的p"。再输出stu[2]的各成员值。在执行p++后,p的值变为stu+3,已不再小于stu+3了,不再执行循环。
注意以下两点:
- 如果p的初值为stu,即指向第一个元素,则p加1后p就指向下一个元素的起始地址。
例如:
(++p)->num 先使p自加1,然后得到它指向的元素中的num成员值(即10102)。
(p++)->num 先得到p->num 的值(即10101),然后使p自加 1,指向 stu[1].请注意以上二者的不同。
(2)程序已定义了p是一个指向struct student类型数据的指针变量,它用来指向一个 struct student型的数据(在例11.4中p的值是stu数组的一个元素(如stu[0],stu[1])的起始地址),不应用来指向stu数组元素中的某一成员。例如,下面的用法是不对的:
p=stu[1].name1
编译时将给出“警告”信息,表示地址的类型不匹配。不要认为反正p是存放地址的,可以将任何地址赋给它。如果要将某一成员的地址赋给p,可以用强制类型转换,先将成员地址转换成p的类型。例如:
p= (struct student* )stu[0].name;
此时.p的值是stu[0]元素的 name成员的起始地址。可以用“printf("%s",p);"输出stu[0]中成员 name 的值,但是P仍保持原来的类型,如果执行“printf("%s",p+1);".则会输出stu[1]中 name的值。执行p+1时,p的值增加了结构体struct student的长度。
3用结构体变量和指向结构体的指针作函数参数
将一个结构体变量的值传递给另一个函数,有3个方法:
(1)用结构体变量的成员作参数。例如,用stu[1].num或stu[2]. name作函数实参,将实参值传给形参。用法和用普通变量作实参是一样的,属于“值传递”方式,应当注意实参与形参的类型保持一致。
(2)用结构体变量作实参。老版本的C系统不允许用结构体变量作实参,ANSIC取看了这一限制。但是用结构体变量作实参时,采取的是“值传递”的方式,将结构体变量所占的内存单元的内容全部顺序传递给形参。形参也必须是同类型的结构体变量。在函数胃用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,如果结构体的规模很大时,开销是很可观的。此外,由于采用值传递方式,如果在执行被调用函数期间改变了形参(也是结构体变量)的值,该值不能返回主调函数,这往往造成使用上的不便。因此一般较少用这种方法。
(3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给
形参
例11.5 有一个结构体变量stu,内含学生学号、姓名和3门课的成绩。要求在main函数中赋以值,在另一函数print中将它们打印输出。
今用结构体变量作函数参数。
#include <string.h>
#define FORMAT " %d\n%s\n%f\n%f\n%f\n"
struct student
{int num ;
char name[20];
float score[3];
}
main()
{void print(struct student );
struct student stu;
stu.num=12345;
strepy(stu, name,"Li Li");
stu. score[0]=67.5;
stu. score[1]=89;
stu.score[2]=78.6;
print(stu);
}
void print (struct student stu)
{
printf(FORMAT,stu.num,stu.name, stu. score[0],stu.score[1].stu. score[2]);
printf("\n" );
}
运行结果为:
12345
Li Li
67.500000
89.000000
标签:变量,指向,struct,name,stu,num,类型,指针 From: https://blog.csdn.net/office_lgirl/article/details/136946546