当前课程知识点:高级语言程序设计 > 指针 > 6.6 指针的指针 > 指针的指针
下面看看指针的指针
指针的指针
我们先讲这一点
准备后面的利用它来访问二维数组
int a=5,*ptr=&a;
这里定义一个指针
int的类型的指针变量ptr
那么把ptr的值初始化为a的地址
那么这个时候我们画示意图就是这个样子
ptr指向a
在这个基础之上
如果我们再定一个指针变量p
让p指向ptr
那么它的示意图就这样
p的值是ptr这个变量的地址
ptr指向a
那么p我们就把它称为指针的指针
因为它指向的对象
P指向的对象仍然是一个指针
所以叫指针的指针
那么我们用C语言
指针的指针可以这样定义
int **p;
两个信号表示指针的指针
那么P的值
我们就可以取ptr的地址
这里要注意
P的值必须是一个int*指针的地址
int*指针的地址
一个指针
如果它指向了对象是一个type*的指针
则称为指针的指针
一般定义形式如下
type**标识符
我们先看看利用指针的指针
来访问单个的整型变量
程序#include
int main( )
花括号里面
int a,*ptr=&a;
指针ptr
指针ptr int*
这个int类型的指针ptr
我们给它初始化为a的地址
然后int **p;
也就是指针的指针
p我们给它赋ptr的地址
把这个值赋值给P
然后调用格式输入函数
我们给a输入值
调用格式输出函数
我们输出a的值
那么从这样来输出a的值
那么a的值除了这种输出方法之外
我们还可以用*ptr
因为ptr这个指针变量
它的值就是a的地址
它又是int*类型的指针
所以它指向的对象就是a
那*ptr和上面的a等价
变量名a在这里等价
那**p是什么意思呢
显然*P就是ptr
因为P的值是ptr的地址
那么星号批相当于ptr
那**P那就相当行*ptr
也就相当于a
所以这里面三个后面
最后的三个输出函数调用里面
都是输出的a的值
但是访问的这个方法不一样
第一个是用数组名a来访问的
第二个是用一个指针变量来访问的
第三个是用指针的指针来访问的
我们可以看到它运行的结果
这个程序运行输入5
把5的值送给a
那么输出来都是5
这三个证明了
我们这样都访问的就是a
这是用指针的的指针访问整型变量
我们总结一下这上面代码的作用下
*p等效于ptr
*ptr等效于a
变量名a
所以**p在这里也等效于a
那么利用指针的指针
我们来进一步访问一维数组
刚才我们是访问的单个的整型变量
我们看一看
看看这下面的这个例子
程序是这样的
#include
int main( )
花括号里
int a[4]
我们定义的一个一维数组
数组名是a
有四个元素
逗号 *ptr;
定义的一个int类型的指针ptr
int **p
定义一个指针的指针p
那么我们把ptr的地址
也就是一个int *
这个指针的地址
赋值给p这是合法的
或ptr我们把它的值从a开始取起
那么ptr的值小于a+4的前提下
我们来输入调用格式输入函数scanf
来输入整数送给ptr的值
它的值是个地址
送给这个地址
由于ptr一开始它的值是a
因此这个写法第一次输入值的话
是送给数组a的第一个元素a[0]
然后再上去ptr增加1
那么就送给数组中的第二个元素a[1]
依次类推
送给下一次a[2]
再下一次送给a[3]
给数组中的四个元素赋值
这是我们利用了int*的这个指针
来访问的这个一维数组
接着我们再来看一看
或ptr 它的值再从a开始取起
也就是再重新让ptr指向一维数组a的第一个元素
然后依次去取a[1]的地址
a[2]的地址
a[3]的地址
那么来输出
输出的时候%d对应的是什么呢
是**p
那么这个**p在这里是什么意思呢
我们看一看
P它的值是ptr的地址
那么*p就相当于是ptr
**p就相当于是*ptr
由于ptr在这个循环里面
它的值在变化
第一次的时候
它就是数组a的第一个元素的地址
首地址
然后ptr+1
那就指向a[1]的
因此随着这个循环的进行
这个**p实际上就是访问了数组中的这四个元素
分别开始访问的是a[0]
第一次访问a[0]
第二次访问的就是a[1]
第三次访问的就是a[2]
第四次访问的就是a[3]
这样我们通过指针的指针
来访问了这个一维数组
这个一维数组a
我们看看运行结果是不是真的是这样
运行结果
我们整个程序运行输入1357
给这个一维数组a输出来
你看也是1357
这样就证明了我们要用这个指针的指针
来访问了这个一维数组
到这里面我们回顾这整个过程
不容易理解的地方就在于ptr在移动
它遍历的数组a的元素
由于这个指针的指针变量p
它是指向ptr
ptr在移动
那**p也就在移动
因此这个**p
它就挨个的访问的整个数组中的元素
这个效果是这样的
指针的指针我们讲完了
下面我们看一看
指针数组
什么是指针数组
元素是指针的数组
我们把它称为指针数组
看一个例子
我们来理解加深理解
它的一般定义形式是type*
标识符 [常量表达式]
或type*
(标识符[常量表达式])
这个时候由于这个标识符和中括号优先结合
中括号优先级高于圆括号
高于这个*
所以这个圆括号是可以去掉的
这是获得情况
我们看看例子
int i,a[4];
int *p[4];
在这里这个p[4]
p先和中括号结合
所以P是个数组
那么剩下来的int*
就是这个数组元素的类型
所以P是一个指针数组
它有四个元素
每一个元素是一个int*类型的指针
int类型的指针
那么我们就可以这样
for(i=0;i<4;i++)
我们把a[i]的地址赋值给p[i]
那么它画一个示意图出来
效果就是这样的
数组p有四个元素
P[0] P[1] P[2] P[3]
那么当我们把a[i]的地址复制给p[i]的时候
那就相当于把a[0]的地址放到p[0]里面了
那a[1]的地址送给的p[1]
a2的这个地址送给了p[2]
a3的地址送给的p[3]
所以p中括号里
那么就指向我们这个a[0]
p[1]指向a[1]
p[2]指向a[2]
p[3]指向a[3]
那么如果我们a[1] a[2] a[3] a[4]的值是1234的话
它的效果就是这样的
这就是指针数组
在这里我们再把指针数组的意思
这个概念表达的意思
再说一下
元素是指针的数组
我们叫指针数组
首先它是个数组
数组中的元素是指针
那么就是指针数组
那么对于这个指针数组每一个元素
那就等同于我们前面讲的指针
那么对每一个数组元素的使用
就相当于使用前面我们
这个指针的方法是一样的
-1.1 计算机程序和计算机语言
-1.2 C程序的构成
--C程序的构成
-1.3 C语言编辑、编译、运行(VC++2010学习版)
-练习题
-2.1 变量的定义和使用
--变量的定义和使用
-2.2 数据类型
--数据类型简介
--整型数据
--实型数据
-2.3 格式输出和格式输入
-2.4 运算符和表达式
--运算符和表达式
-2.5 结构化程序设计入门
-练习题
-3.1 为什么要用选择结构解决问题
-3.2 如何正确表示选择结构中的条件
-3.3 用if语句及if语句嵌套实现选择结构
-3.4 用switch语句实现选择结构
-练习
-4.1 循环的引入
-4.1 循环的引入--作业
-4.2 用while语句实现循环
-4.3 用do-while语句实现循环
-4.4 用for语句实现循环
-- 用for语句实现循环
-4.4 用for语句实现循环--作业
-4.5 何时需要用循环的嵌套
-4.6 如何提前终止循环和提前结束本次循环
-习题--作业
-5.1 数组类型的引入
--数组类型的引入
-5.2 一维数组的定义和初始化
-5.3 一维数组的使用
--一维数组的使用
-5.4 二维数组的定义和初始化
-5.5 二维数组的使用
--二维数组的使用
-习题--作业
-6.1 什么是指针
--什么是指针
-6.2 指针类型及相关概念
-6.3 指针变量的定义、赋值与使用
-6.4 指针的运算
--指针的运算
-6.5 指针与一维数组
--指针与一维数组
-6.6 指针的指针
--指针的指针
-6.7 指针与二维数组
--指针与二维数组
-习题--作业
-7.1 为什么要自定义函数
-7.2 函数的定义
--函数的定义
-7.3 函数的调用
--函数的调用
-7.4 函数参数的传递
--函数参数的传递
-7.5 函数的嵌套调用和递归调用
-7.6 变量的作用域和存储类型
-习题--作业
-8.1 字符串的存储及输入输出
-8.2 系统字符串处理函数
-8.3 自定义字符串处理函数
-习题--作业
-9.1 结构体类型的定义
--结构体类型的定义
-9.2 结构体变量及指针变量的定义及使用
-9.3 结构体变量和指针变量作函数的参数
-9.4 结构体数组的定义和使用
-9.5 共用体类型和枚举类型
--共用体和枚举类型
-习题--作业
-动态内存分配--习题
-习题--作业