C语言指针结构体详解,结构体指针,C语言结构体指针详解

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

指向结构体变量的指针

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

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

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

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

# include

# include

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

# include

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语言字节对齐问题详解

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

Linux C 语言之 Hello World 详解

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

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

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

C语言字节对齐问题详解

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

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

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

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

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

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

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

c语言文件操作函数详解

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

C语言链表各类操作详解

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

【C语言】printf函数详解

C语言printf函数详解 一.相关基础知识 请求printf()打印变量的指令取决于变量的类型,例如打印整数用%d符号,打印字符用%c符号,这些符号称为转换说明(conversion specifi ...

随机推荐

QoS 测量 (目标,方法,协议)

本文翻译自ITU-T的Technical Paper:

spring+mybatis的优缺点

mybatis的优缺点: 优点: 1. 易于上手和掌握. 2. sql写在xml里,便于统一管理和优化. 3. 解除sql与程序代码的耦合. 4. 提供映射标签,支持对象与数据库的orm字段关系映射 ...

【转】android应用开发全程实录-你有多熟悉listview?---不错

原文网址:http://www.cnblogs.com/noTice520/archive/2011/12/05/2276379.html 今天给大家带来 ...

CCF系列之日期计算(201509-2)

试题编号: 201509-2 时间限制: 1.0s 内存限制: 256.0MB 问题描述 给定一个年份y和一个整数d,问这一年的第d天是几月几日? 注意闰年的2月有29天.满足下面条件之一的是闰年: ...

pipe size设置

我所用的软件架构,使用pipe来实现线程之间的大量数据的传输.在实际操作中,pipe中传输的是数据的指针,而不是数据本身.  但是在调试过程中,我发现,如果我尝试往pipe里面write10000个指 ...

[Leetcode]237. Delete Node in a Linked List -David_Lin

Write a function to delete a node (except the tail) in a singly linked list, given only access to th ...

[转] Form 表单数据处理 简单教程 formidable 使用心得

入门,高手见笑 表单数据一种是get方式, 另一种是post 方式 1.get方式 对于get方式,node处理起来非常简单 如以下代码: var urlParsed = url.parse(requ ...

Unity中的定时器与延时器

JavaScript中的定时器与延时器,分别是 setInterval.setTimeout,对应的清理函数是:clearInterval.clearTimeout. 而在Unity中,则分别是:In ...

随机数的组合问题(JavaScript描述)

随机数的组合问题在面试时是经常考的,比如之前我就被问到:“有一个可以生成1-5的随机数函数,怎样把它扩大到1-7?” 在解决这个问题之前,先来看看另外一个比较简单的问题:“有一个可以生成1-7的函数, ...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值