| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 庖丁解牛 指针的高端操作 -> 正文阅读 |
|
[C++知识库]庖丁解牛 指针的高端操作 |
本章重点 写在前面在初阶c语言之浅识指针中,我已经详细地介绍了指针的概念:
接下来我们就进入指针的高阶主题继续深入的了解指针。
1.字符指针
在指针的类型中我们知道还有一种指针类型为字符指针char*
简单的使用:
还有一种使用方式如下:
代码const char* pstr = "hello world";特别容易让同学以为是把字符串 hello world放到字符指针 pstr 里了,但是本质是把字符串 hello world首字符的地址放到了pstr中。 上面代码的意思是把一个常量字符串的首字符 h 的地址(0x0012ff44)存放到指针变量 pstr 中。 有这样一道题目:
我们不妨先来猜猜结果,然后来看答案: 是否与你的想法有所差异呢? 原因是这样:
2.指针数组在初阶c语言之浅识指针中,我们已经学习过指针数组。这里简单回忆一下:
3.数组指针3.1数组指针的定义
数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉:
整形指针:
int * pint
;
能够指向整形数据的指针。
浮点型指针:
float * pf
;
能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
那么下面代码哪个是数组指针?
答案是下面的代码。那么我来解释一下为什么数组指针长这个样子:
3.2 &数组名VS数组名
对于下面的数组:
arr 和& arr 分别是啥? 我们知道arr是数组名,数组名表示数组首元素的地址。 那&arr数组名到底是啥? 我们看一段代码:
运行结果如下: 可见数组名和&数组名打印的地址是一样的。
难道两个是一样的吗?
我们再看一段代码:
运行之后: 根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上:
&arr
表示的是
数组的地址
,而不是数组首元素的地址。(细细体会一下)
本例中
&arr
的类型是:
int(*)[10]
,是一种数组指针类型
数组的地址 +1 ,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是 40 3.3 数组指针的使用
那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
看代码:
数组指针使用实例:
二维数组与数组指针这里有非常重要的一点,我们已经知道数组名就是数组首元素的地址(有两个例外),那么对于二 维数组来说,二维数组的首元素是什么呢?其实就是第一行数组。 如图所示,我们给arr+1之后,它的地址跳过了一个一维数组的大小。所以我们可以通俗的把二维 数组arr理解为,arr数组包含3个元素,每个元素都是元素个数为5、元素类型为int类型的数组。 我们甚至可以换一种方式来定义二维数组:
定义太复杂看不懂? 没关系我们细致分解:
接下来,我们尝试认识并解释下面代码:
4.数组参数和指指针参数
在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
4.1一维数组传参如果我们要将如下两个数组作为参数传递给test函数
下面展示的几种设计方式都是正确的:
有的小伙伴可能不明白为何可以用指针作为参数来接收一维数组。 是因为,我们调用test函数时,都将数组名传递过去,而数组名又是首地址,当然可以用一个指针 变量来接收。 对于arr1,是一个整型数组,元素类型为int ,所以用int*的指针来接收; 对于arr2,是一个指针数组,元素类型为int* ,所以用int**的二级指针来接收。 4.2 二维数组传参
如果我们要将二维数组arr传递给test函数,那么test函数又该如何如何设计呢?
如上面代码所示,除了被注释掉的代码,其他的都是行得通的。 对于第二种格式为什么是错的,是因为有这样的规定:
总结:二维数组传参,函数形参的设计只能省略第一个
[]
的数字。
因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。 这样才方便运算。
第四、五两种形式是接收一维数组的设计。
那么最后两种又为什么行呢?
参照第三节最后的二维数组与数组指针就不难理解了。
原因就是,二维数组的数组名就是首元素地址。而其实二维数组的每个元素又是一个数组。所以
我们可以用数组指针 int(*arr)[5] 或是 二级指针来接收。
4.3一级指针传参一级指针传参相对简单,就用一个指针变量接收即可。 一级指针运用实例:
4.4二级指针传参同样的,二级指针传参,也只需一个二级指针即可。 例如:
思考一下: 通过前面的二级指针与二维数组的关系,分析一下当函数的参数为二级指针时,可以接收什么参 数?大致有这么几种:
5.函数指针之前学到,&+变量名可以得到变量的地址,&+数组名可以取出数组的地址(其实是数组首元素的地址)。那么当我们第一次听到函数指针这个概念时,有没有首先想到函数也会有地址吗?怎么得到函数的地址?难道&+函数名就可以得到函数的地址吗? 其实还真是,看以下操作:
结果如下: 我们发现,不仅&+函数名可以得到函数的地址,就连函数名本身也是函数的地址。 既然得到了函数的地址,我们如何将函数的地址保存起来呢? 这就要用到函数指针了。 5.1函数指针的定义下面我们看代码:
首先,能给存储地址,就要求
pfun1
或者
pfun2
是指针,那哪个是指针?
答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参
数,返回值类型为void。
下面我们多练习如何认识函数指针:
6.函数指针数组首先提问,函数指针数组是一个指针还是数组?答案是是一个数组。
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义
呢?
再多举几个例子吧:
函数指针数组有什么用途呢? 例如,我们现在要实现一个计算器,包含加减乘除四种功能。我们可以将这四种功能分别用四个函 数来实现。然后将四个函数对应的函数指针保存到一个函数指针数组里。当我们运行计算器的程序 时,可以根据选择不同功能的选项,来找到函数指针数组不同下标所对应的不同函数,进行运算。 由于代码太长,将计算器的代码实现放在文章末尾。 7.指向函数指针数组的指针首先,指向函数指针数组的指针是一个指针。
指针指向一个数组,数组的每个元素都是函数指针。
那么该如何定义一个指向函数指针数组的指针呢?
如果给我们一个指向函数数组的指针,我们不会辨别怎么办? 没关系,我们逐步来分解:
8.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
行响应。具体的使用我们以库函数qsort为例。
附:
计算器一般实现:
计算器函数指针数组的实现:
本章完! |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/11 14:21:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |