结构指针的使用

结构指针的使用

指针类型变量:

指针类型,是变量类型的一种,它是专门用来存储变量的地址的。

例如 int *p; 表示p是一个指针变量,它用来存储某个整型变量的地址。

int a=5;

int *p=&a;

这样,就将整型变量a的地址存储在了p中。

如图示所示:

变量a中存储的是5,它自身的地址是 0x001A

变量p中存储的是0x001A,也就是a的地址,它自身的地址是0x10AB

下面是一个结构指针:

//定义结点数据类型:

typedef struct

{

float coef;

int expn;

}term, ElemType;

//定义结点,及指向结点的指针

typedef struct LNode

{

ElemType data;

struct LNode *next;

}LNode, *LinkList;

这里,定义了一个链表的结点,它的数据项包括 coef, expn,就是系数和指数。还包括一个指向下一个结点的指针。

给这个结构定义了两个别名:

一个是LNode,用来代替struct LNode

还有一个是LinkList,是指向结点的指针,用来代替 struct LNode *

如果定义了这样一个变量p: LinkList p;

那么它就是一个指向结点的指针,它在内存中的存储可以用下图表示:

这个指针变量p是用来存储结构型变量的地址的。

具体说就是这种结构型变量的地址:struct LNode别名为LNode。现在,它的值是空的,因为还没有为它赋值。指针变量本身也需要占用内存空间,因此,指针变量p本身的内存地址是0xA01C。

现在,定义一个结构型变量:

LNode n1; 假设它的地址是 0x013B

给这个结构型变量赋值:

n1.coef=1.5;

n1.expn=2;

n1.next=NULL

那么它在内存中的存储情况如图:

之后,把结点n1的地址赋值给指针 p

p=&n1; &是取地址符号

当使用*p时候,*称为引用符号,就是对结构型变量n1的引用,就是顺着p存储的地址0x013B找到结构型变量n1,并使用它。例如,(*P).coef 是1.5 (*p).expn是2。

还有一种使用结构指针的方法,就是用 ->代替 (*).因为前者意义明确,书写简洁。可以写成这样:p->coef 或 p->expn

示例程序如下:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
 float coef;
 int   expn;
}term, ElemType;


typedef struct LNode
{
 ElemType      data;
 struct LNode *next;	
}LNode, *LinkList;



main()
{
 LNode n1;
 LinkList p;
 
 n1.data.coef = 1.5; 
 n1.data.expn = 2; 
 n1.next = NULL; 
 
 p=&n1;
 
 printf("coef=%f  expn=%d \n",(*p).data.coef, (*p).data.expn);		
}

指针作为参数传递给函数:

一种情况是,传递指针的拷贝。即指针作为实参,被调用函数中是形参。形参就像临时变量一样,当函数调用结束后就自动销毁掉了。

例如,有这样一个结构体变量n1,它在内存中的地址是0x013B,它包括两个数据成员coef=1.5,expn=2,和一个指向下一个结点的指针next=NULL。

有一个指针变量p它的地址是0xA01C,将结构体变量n1的地址赋值给p

p=&n1; 此时,p的值为0x013B。

现在,想要在一个函数func中打印结构体n1的数据,那么指针p的值将作为实参,拷贝一份给形参pf。注意,这里实参p和形参pf的地址是不一样的。

在func函数中可以引用pf中的地址值,找到结构体n1的位置,从而打印数据。

如图所示:

示例程序:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
 float coef;
 int   expn;
}term, ElemType;


typedef struct LNode
{
 ElemType      data;
 struct LNode *next;	
}LNode, *LinkList;


void func(LinkList pf)
{
 printf("coef=%f  expn=%d \n",(*pf).data.coef, (*pf).data.expn);		
}

main()
{
 LNode n1;
 LinkList p;
 
 n1.data.coef = 1.5; 
 n1.data.expn = 2; 
 n1.next = NULL; 
 
 p=&n1;
 
 func(p);	
}

还有一种情况:

如果需要改变指针本身的值,就不能只是传递指针的拷贝,而是需要传递指针的地址:

例如,定义了两个结构体结点n1,n2。如果需要在函数func中将指针p的值修改为n2的地址,那么就需要传递指针的地址过去,如果只是修改形参的值,不会对实参p起到任何影响,如图所示:

如何在函数func中修改实参p的值为0x015F,使它指向结点n2呢?那就需要在给func传递参数的时候,传递的是p的地址:func(&p)。&是取地址符号,也就是传递的是0xA01C,之后在func中对此地址进行引用,就能修改p的值了。

但是这时,形参的类型不再是LinkList型了,而是 LinkList *,也就是指向指针的指针,也就是一个二级指针,如果不用别名,而是写完整的话,应该是:

func(struct LNode **pf ) 用定义好的别名简写成 func(LinkList * pf)

pf是一个指针,它存储的是某种数据类型的地址。

哪种数据呢?是一个指针类型。

指向什么的指针呢?指向结构struct LNode的指针。

对pf的引用,首先找到p,即*pf

再对p引用,又找到n2,即*(*pf)

因此(**pf).data.coef 应该是 2.5 (**pf).data.expn 应该是3

如图所示:

示例程序如下:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
 float coef;
 int   expn;
}term, ElemType;


typedef struct LNode
{
 ElemType      data;
 struct LNode *next;	
}LNode, *LinkList;

LNode n1,n2; 

//在函数中修改指针所指向的值 
void func(LinkList *pf)
{
 *pf=&n2;	
 printf("在函数func中打印 coef= %f  expn = %d\n",(**pf).data.coef, (**pf).data.expn);
}


main()
{
 LinkList p;
 
 n1.data.coef = 1.5; 
 n1.data.expn = 2; 
 n1.next = NULL; 
 
 n2.data.coef = 2.5;
 n2.data.expn = 3;
 n2.next = NULL;
 
 //是p指向 结点 n1 
 p=&n1;
 //打印其值 
 printf("coef=%f  expn=%d\n",p->data.coef , p->data.expn );
 
 //改变指针p的指向 
 printf("改变p值后\n");
 func(&p);	
 
 //打印其值 
 printf("在主函数中打印\n");
 printf("coef=%f  expn=%d\n",p->data.coef , p->data.expn );
}
相关推荐
小明说Java35 分钟前
常见排序算法的实现
数据结构·算法·排序算法
小熳芋6 小时前
验证二叉搜索树- python-递归&上下界约束
数据结构
不穿格子的程序员9 小时前
从零开始写算法——链表篇2:从“回文”到“环形”——链表双指针技巧的深度解析
数据结构·算法·链表·回文链表·环形链表
诺....10 小时前
C语言不确定循环会影响输入输出缓冲区的刷新
c语言·数据结构·算法
长安er11 小时前
LeetCode876/141/142/143 快慢指针应用:链表中间 / 环形 / 重排问题
数据结构·算法·leetcode·链表·双指针·环形链表
workflower11 小时前
PostgreSQL 数据库的典型操作
数据结构·数据库·oracle·数据库开发·时序数据库
仰泳的熊猫12 小时前
1140 Look-and-say Sequence
数据结构·c++·算法·pat考试
EXtreme3512 小时前
栈与队列的“跨界”对话:如何用双队列完美模拟栈的LIFO特性?
c语言·数据结构·leetcode·双队列模拟栈·算法思维
松涛和鸣12 小时前
29、Linux进程核心概念与编程实战:fork/getpid全解析
linux·运维·服务器·网络·数据结构·哈希算法