结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针。

指向结构体变量的指针

前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针。

前面讲过,&student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址。如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员。

那么,这个指针变量定义成什么类型呢?只能定义成结构体类型,且指向什么结构体类型的结构体变量,就要定义成什么样的结构体类型。比如指向 struct STUDENT 类型的结构体变量,那么指针变量就一定要定义成 struct STUDENT* 类型。

下面将前面的程序用指针的方式修改一下:

# include <stdio.h>
# include <string.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[]; //姓名
int num; //学号
struct AGE birthday; //生日
float score; //分数
};
int main(void)
{
struct STUDENT student1; /*用struct STUDENT结构体类型定义结构体变量student1*/
struct STUDENT *p = NULL; /*定义一个指向struct STUDENT结构体类型的指针变量p*/
p = &student1; /*p指向结构体变量student1的首地址, 即第一个成员的地址*/
strcpy((*p).name, "小明"); //(*p).name等价于student1.name
(*p).birthday.year = ;
(*p).birthday.month = ;
(*p).birthday.day = ;
(*p).num = ;
(*p).score = ;
printf("name : %s\n", (*p).name); //(*p).name不能写成p
printf("birthday : %d-%d-%d\n", (*p).birthday.year, (*p).birthday.month, (*p).birthday.day);
printf("num : %d\n", (*p).num);
printf("score : %.1f\n", (*p).score);
return ;
}

输出结果是:
name : 小明
birthday : 1989-3-29
num : 1207041
score : 100.0

我们看到,用指针引用结构体变量成员的方式是:

(*指针变量名).成员名

注意,*p 两边的括号不可省略,因为成员运算符“.”的优先级高于指针运算符“*”,所以如果 *p 两边的括号省略的话,那么 *p.num 就等价于 *(p.num) 了。

从该程序也可以看出:因为指针变量 p 指向的是结构体变量 student1 第一个成员的地址,即字符数组 name 的首地址,所以 p 和 (*p).name 是等价的。

但是,“等价”仅仅是说它们表示的是同一个内存单元的地址,但它们的类型是不同的。指针变量 p 是 struct STUDENT* 型的,而 (*p).name 是 char* 型的。所以在 strcpy 中不能将 (*p).name 改成 p。用 %s 进行输入或输出时,输入参数或输出参数也只能写成 (*p).name 而不能写成 p。

同样,虽然 &student1 和 student1.name 表示的是同一个内存单元的地址,但它们的类型是不同的。&student1 是 struct STUDENT* 型的,而 student1.name 是 char* 型的,所以在对 p 进行初始化时,“p=&student1;”不能写成“p=student1.name”。因为 p 是 struct STUDENT* 型的,所以不能将 char* 型的 student1.name 赋给 p。

此外为了使用的方便和直观,用指针引用结构体变量成员的方式:

(*指针变量名).成员名

可以直接用:

指针变量名->成员名

来代替,它们是等价的。“->”是“指向结构体成员运算符”,它的优先级同结构体成员运算符“.”一样高。p->num 的含义是:指针变量 p 所指向的结构体变量中的 num 成员。p->num 最终代表的就是 num 这个成员中的内容。

下面再将程序用“->”修改一下:

# include <stdio.h>
# include <string.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[]; //姓名
int num; //学号
struct AGE birthday; /*用struct AGE结构体类型定义结构体变量birthday, 生日*/
float score; //分数
};
int main(void)
{
struct STUDENT student1; /*用struct STUDENT结构体类型定义结构体变量student1*/
struct STUDENT *p = NULL; /*定义struct STUDENT结构体类型的指针变量p*/
p = &student1; /*p指向结构体变量student1的首地址, 即第一项的地址*/
strcpy(p->name, "小明");
p->birthday.year = ;
p->birthday.month = ;
p->birthday.day = ;
p->num = ;
p->score = ;
printf("name : %s\n", p->name); //p->name不能写成p
printf("birthday : %d-%d-%d\n", p->birthday.year, p->birthday.month, p->birthday.day);
printf("num : %d\n", p->num);
printf("score : %.1f\n", p->score);
return ;
}

结构体指针,C语言结构体指针详解的更多相关文章

  1. [转]C语言字节对齐问题详解

    C语言字节对齐问题详解 转载:https://www.cnblogs.com/clover-toeic/p/3853132.html 引言 考虑下面的结构体定义: typedef struct{ ch ...

  2. Linux C 语言之 Hello World 详解

    目录 Linux C 语言之 Hello World 详解 第一个 C 语言程序 程序运行原理 编译,链接 运行时 链接库 编译器优化 Hello World 打印原理 stdout, stdin 和 ...

  3. R语言服务器程序 Rserve详解

    R语言服务器程序 Rserve详解 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒.直到 ...

  4. C语言解决约瑟夫问题详解的代码

    将开发过程中比较重要的一些内容做个收藏,下面的内容是关于C语言解决约瑟夫问题详解的内容,希望能对码农有帮助. #pragma once #include<vector> class PRO ...

  5. C语言字节对齐问题详解

    引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...

  6. C语言预处理器命令详解【转】

    本文转载自:http://www.cnblogs.com/clover-toeic/p/3851102.html 一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所 ...

  7. C语言字节对齐问题详解(对齐、字节序、网络序等)

    首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...

  8. C语言字节对齐问题详解【转】

    引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...

  9. c语言文件操作函数详解

    一.文件操作注意点: 1 打开文件时,如果打开方式加“+”,表示该文件可以“写” ; 2 退出程序一般用exit函数,正常退出参数为0,非正常退出参数为正零值 ; 3 文件的读写操作:按字符.字符串. ...

  10. C语言链表各类操作详解

    链表概述 链表是一种常见的重要的数据结构.它是动态地进行存储分配的一种结构.它可以根据需要开辟内存单元.链表有一个“头指针”变量,以head表示,它存放一个地址.该地址指向一个元素.链表中每一个元素称 ...

随机推荐

  1. rabbitmq 和 kafka 简单的性能测试

    测试环境:ubuntu 15.10 64位 cpu:inter core i7-4790 3.60GHZ * 8 内存:16GB 硬盘:ssd 120GB 软件环境:rabbmitmq 3.6.0   ...

  2. JMS学习八(ActiveMQ消息持久化)

    ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB,还有一种内存存储的方式,由于内存不属于持久化范畴,而且如果使用内存队列,可以考虑使用更合适的产品,如ZeroMQ.所以 ...

  3. 大哥带的Orchel数据库时间盲注

    0X01Oracle基于延时的盲注总结 0x00 前言 oracle注入中可以通过页面响应的状态,这里指的是响应时间,通过这种方式判断SQL是否被执行的方式,便是时间盲注: oracle的时间盲注通常 ...

  4. [CSP-S模拟测试]:取石子(博弈论+DP)

    题目描述 有三堆石子,它们的石子个数分别为$x,y,z$.$A$和$B$正在博弈,由$A$先手,双方轮流操作.每次操作是指,选择若干堆($1-3$堆)石子,从中各取出相同数量的石子(不能$1$个都不取 ...

  5. android和网络连接相关的类URL,URLConnection,HttpURLConnection,HttpClient

    这几个类都是用于和服务器端的连接,有些功能都能够实现,关系是: 一.URL URL标识着网络上的一个资源:该类包含一些URL自身的方法,如获取URL对应的主机名称,端口号,协议,查询字符串外,还有些方 ...

  6. 后盾网lavarel视频项目---laravel 使用laracasts/flash插件提示信息

    后盾网lavarel视频项目---laravel 使用laracasts/flash插件提示信息 一.总结 一句话总结: laracasts/flash插件的效果就是一个弹出的boostrap模块框, ...

  7. Abrt

    https://abrt.readthedocs.io/en/latest/faq.html#unpackaged

  8. 使用SSH和Nginx做内网HTTP映射

    https://blog.csdn.net/imdyf/article/details/80143991

  9. 【零售小程序】—— webview嵌套web端项目(原生开发支付功能)

    index → index.wxml  套webwiew // url 活动url bindmessage 接收信息 <web-view src='{{url}}' bindmessage='m ...

  10. leetcode 590.N-ary Tree Postorder Traversal N叉树的后序遍历

    递归方法 C++代码: /* // Definition for a Node. class Node { public: int val; vector<Node*> children; ...