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

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

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

6.1 指向结构体变量的指针

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

#include <string.h>

#include <stdio.h>

#include <stdlib.b>

struct student

{

  long num;

  char name[20];

  char sex;

  float score;
};

void main()

{

  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);

  system("pause");
}

  在主函数中声明了 struct student 类型,然后定义了一个 struct student 类型的变量,stu_1 同时又定义一个指针变量 p ,它指向一个 struct student 类型的数据,在函数的执行部分将结构体变量 stu_1 的起始地址赋给指针变量 p ,也就是使 p 指向 stu_1 然后对 stu_1 的各成员赋值,第二个 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。

也就是说以下三种形式等价:

  a. 结构体变量.成员名

  b. (*p).成员名

  c. p->成员名

  上面的最后一个 printf 函数输了项可以改写为

  printf("NO. :%ld\nname: %s\nsex:%c\nscore:%f\n",p->num, p->name, p->sex, p->score);

  其中 -> 称为指向运算符。

  分析以下几种运算符

  p -> n 得到 p 指向的结构体变量中的成员 n 的值

  p -> n ++ 得到 p 指向的结构体变量中的成员 n 的值,用完值后使它加1

  ++p -> n 得到 p 指向的结构体变量中的成员 n 的值使之加 1 (先加)

6.2 指向结构体数组的指针

  以前介绍过可以使用指向数组或数组元素的指针和指针变量,同样,对结构体数组及其元素也可以用指针变量来指向。

  指向结构体数组的指针的应用

#include <stdio.h>

#inlcude <stdlib.h>

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},

             {10103, "Wang Min", 'F', 20}};

void 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);

  system("pause");
}

运行结果如下:

No.  name    sex    age
10101 Li Lin                M     18
10102 Zhang Fun        M     19
10103 Wang Min          F      20

注意以下两点:

(1)如果 p 的初值为 stu,即指向第一个元素,则 p + 1 后指向下一个元素的起始地址。例如:

  (++p) -> num 先使 p 自加 1 ,然后得到它指向的元素中的 num 成员的值(即10102)。

  (p++) ->num 先得到 p->num 的值(即10101),然后使 p 自加 1 ,指向 stu[1]。

  注意以上二者的不同。

  (2)程序已定义了指针 p 为指向 struct student 类型数据的变量,它只能指向一个 struct student 型的数据(p 的值是 stu 数组的一个元素的起始地址),而不能指向 stu 数组元素中的某一成员,(即 p 的地址不能是成员地址)。例如,下面是不对的:

  p = &stu[1].name

编译时将出错。千万不要认为反正 p 是存放地址的,可以将任何地址赋给它。如果地址类型不相同,可以用强制类型转换。例如:

  p = (struct student *)&stu[1].name;

此时,在 p 中存放 stu[1] 元素的 name 成员的起始地址。

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

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

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

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

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

用结构体变量作函数参数。

#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];

};

void print(struct student stu)

{

  printf(FORMAT, stu.num, stu.score[0], stu.score[1], stu.score[2]);

  printf("\n");
}

void main()

{

  struct student stu;

  stu.num = 12345;

  strcpy(stu.name, "Li Li");

  stu.score[0] = 67.5;

  stu.score[1] = 89;

  stu.score[2] = 78.6;

  printf(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, "Li Li", 67.5, 89, 78.6};

void print(struct student *p)

{

  printf(FORMAT, p->num, p->name, p->score[0], p->score[1], p->score[2]);

  printf("\n");
}

void main()

{

  print(&stu);
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值