指向结构体类型数据的指针

一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量.用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。

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。也就是说,以下三种形式等价:

  1. 结构体变量.成员名
  2. (*p).成员名
  3. 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了,不再执行循环。

注意以下两点:

  1. 如果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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光向日葵之沈阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值