C语言学习——指向结构体类型数据的指针

目录

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

指向结构体变量的指针

指向结构体数组元素的指针

用结构体变量和指向结构体的指针作函数参数


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

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

指向结构体变量的指针

这里通过一个简单的例子来说明指向结构体变量的指针变量的应用。

指向结构体变量的指针的应用。

#include<stdio.h>
#include<string.h>
​
int 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 = 1234;
    strcpy(stu_1.name,"Li");
    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) ;
    return 0;
}
​
//输出结果:
No.:1234
name:Li
sex:M
score:89.500000
No.:1234
name:Li
sex:M
score:89.500000 
//可见  两个运行结果是相同的

注意,*p两侧的括号不可省略,因为成员运算符“ . ”优先于“ * ”运算符,*p.num就等价于 *(p.num)了。

为了使用方便和使之直观,可以把*p.num改用p->num来代替,它表示p所指向的结构体变量中的num成员。同样的, ( *p).name等价于p->name,也就是说,下列3种关系等价:

  • 结构体变量.成员名

  • (*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,然后再使用它。
指向结构体数组元素的指针

指向结构体数组元素的指针的应用。

#include<stdio.h>
​
struct student{
        long num;
        char name[20];
        char sex;
        int age;
    };  
​
struct student stu[3] = {
    {10101,"Li-1",'M',18},
    {10102,"Li-2",'M',19},
    {10103,"Li-3",'F',20}
};
​
int main()
{
    struct student *p;
    printf("No.     Name     sex     age\n");
    for(p=stu;p<stu+3;p++)
    {
        printf("%5d%7s%7c%8d\n",p->num,p->name,p->sex,p->age);
    }
    return 0;
}
 

程序分析:

p是指向struct student结构体类型数据的指针变量。在for语句中先使p的初值为stu,也就是数组第一个元素的起始地址。在第一次循环中输出stu[0]的各个成员的值。然后执行p++,使p自加1。p自加1意味着p所增加的值为结构体数组stu的一个元素所占字节数(在本例代码中为2+20+1+2=25字节)。执行p++后p的值等于stu+1,p指向stu[1]。在第二次循环中输出stu[1]的各成员值。在执行p++后,p的值等于stu+2,再输出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].

    (注意两者的不同)

  • 程序已定义了p是一个指向struct student类型数据的指针变量,它用来指向一个struct student类型的数据,不应该用来指向stu数组元素的某一成员。

用结构体变量和指向结构体的指针作函数参数

将一个结构体变量的值传递给另一个函数,有以下3种方法。

(1)用结构体变量的成员作参数。例如:用stu[1].num或stu[2].name作函数实参,将参数值传给形参。用法和普通变量作实参是一样的,属于“值传递”方式。应该注意实参和形参的类型保持一致。

(2)用结构体变量作实参。用结构体变量作实参时,采取的也是“值传递”的方式,将结构体变量所占的内存单元的内容全部顺序传递给形参,形参也必须是同类型的结构体变量。在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,如果结构体的规模很大,开销是很可观的。此外,由于采用值传递方式,如果在执行被调用函数期间改变了形参(也就是结构体变量的值),该值不能反回主调函数,这往往造成使用上的不便。因此一般较少使用这种方法。

(3)指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。

有一个结构体变量stu,内含学生学号、姓名和3门课程成绩。要求在main函数中赋值,在另一个函数print中将它们输出。

#include<stdio.h>
#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];
};
​
int main()
{
    void print(struct student);
    struct student stu;
    stu.num = 12345;
    strcpy(stu.name,"Yang");
    stu.score[0] = 77;
    stu.score[1] = 68;
    stu.score[2] = 89;
    print(stu);
    return 0;
 } 
 
 void print(struct student stu)
 {
    printf(FORMAT,stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2]);
    printf("\n");
 }
 
 //输出:
12345
Yang
77.000000
68.000000
89.000000 

struct student被定义为外部的类型,这样,同一源文件中的各个函数都可以用它来定义变量。main函数中,stu定义为struct student类型变量,print函数中的形参stu也定义为struct student类型变量。在main函数中对stu的各个成员赋值。在调用print函数时,以stu为实参向形参stu实行“值传递”。在print函数中输出结构体变量stu各个成员的值。

将上面的题目改用指向结构体变量的指针作实参。

#include<stdio.h>
#define FORMAT "%d\n%s\n%f\n%f\n%f\n"
​
struct student{
    int num;
    char name[20];
    float score[3];
}stu={12345,"Yang",77,68,89};
​
int main()
{
    void print(struct student * );  //形参类型修改成指向结构体的指针变量 
    print(&stu);                    //实参改为stu的起始地址 
    return 0;
 } 
 
 void print(struct student *p)  //形参类型修改了 
 {
    printf(FORMAT,p->num,p->name,p->score[0],p->score[1],p->score[2]);  //用指针变量调用各个成员的值 
    printf("\n");
 }
 
 //输出:
//12345
//Yang
//77.000000
//68.000000
//89.000000 

此程序改用在定义结构体变量stu时赋初值,这样程序可以简化些。print函数中的形参p被定义为指向struct student类型数据的指针变量。注意在调用print函数时,用结构体变量stu的起始地址&stu作实参。在调用函数时将该地址传给形参p(p是指针变量)。这样p就指向了stu。在print函数中输出p所指向的结构体变量的各个成员的值,它们就是stu的成员值。

用指针作函数参数较好,能提高运行效率。

声明:本文章为个人学习笔记,资料整理参考谭浩强《C程序设计(第三版)》如有错误,欢迎大家指正! 

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值