前言

接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针

 

一、返回指针的函数

指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的。

返回指针的函数的一般形式为类型名 * 函数名(参数列表) eg: char * upper(参数){} 返回指向char型的指针变量

比如下面这个函数,返回一个指向char类型变量的指针

 1 // 需求:将字符串str中的小写字母变成大写字母,并返回改变后的字符串
2 // 注意的是:这里的参数要传字符串变量,不能传字符串常量
3 char * upper(char *str) {
4 // 先保留最初的地址。因为等会str指向的位置会变来变去的。
5 char *dest = str;
6
7 // 如果还不是空字符
8 while (*str != '\0') {
9 // 如果是小写字母
10 if (*str >= 'a' && *str <= 'z') {
11 // 变为大写字母。小写和大写字母的ASCII值有个固定的差值
12 *str -= 'a' - 'A';
13 }
14
15 // 遍历下一个字符
16 str++;
17 }
18
19 // 返回字符串
20 return dest;
21 }

里面的代码我就不详细解释了,重点看第2行的定义形式。

调用这个函数也非常简单:

int main()
{
// 定义一个字符串变量
char str[] = "lmj"; // 调用函数
char *dest = upper(str); printf("%s", dest);
return 0;
}

输出结果:

二、指向函数的指针

看到这个标题,你可能觉得很诧异,指针竟然可以指向一个函数,那我就先解释一下为什么指针可以指向一个函数

1.为什么指针可以指向一个函数

函数作为一段程序,在内存中也要占据部分存储空间,它也有一个起始地址,即函数的入口地址。函数有自己的地址,那就好办了,我们的指针变量就是用来存储地址的。因此,可以利用一个指针指向一个函数。其中,函数名就代表着函数的地址。

2.指向函数的指针的定义

定义的一般形式:函数的返回值类型 (*指针变量名)(形式参数1, 形式参数2, ...);

注意:形式参数的变量名可以省略,甚至整个形式参数列表都可以省略

 1 #include <stdio.h>
2
3 int sum(int a, int b) {
4 return a + b;
5 }
6
7 int main()
8 {
9 // 定义一个指针变量p,指向sum函数
10 int (*p)(int a, int b) = sum;
11 // 或者 int (*p)(int, int) = sum;
12 // 或者 int (*p)() = sum;
13
14 // 利用指针变量p调用函数
15 int result = (*p)(1, 3);
16 // 或者 int result = p(1, 3);
17
18 printf("%d", result);
19 return 0;
20 }

* 第10行定义了一个指向sum函数的指针变量p。p的定义形式为:int (*p)(int a, int b),第1个int代表sum函数的返回值是int类型,然后*p是用括号()包住的,后面的int a和int b代表着sum函数的形参,其实完全可以省略。第10行、11行、12行都是可行

* 在第15行,先利用*p取出指向的函数,再传入参数调用函数。也可以采用第16行中的做法,这样就跟调用普通函数没什么区别

最后的输出结果:,毫无意外

3.使用注意

1> 由于这类指针变量存储的是一个函数的入口地址,所以对它们作加减运算(比如p++)是无意义的。难道p++就会指向下一个函数了?可笑至极!!没这回事。

2> 返回指针的函数的定义char *upper(char *str) 和 指向函数的指针的定义int (*p)(int a, int b)非常相似,使用时特别注意区分

3> 指向函数的指针变量主要有两个用途:

  • 调用函数

  • 将函数作为参数在函数间传递。我这么一说,可能还不是很明白,举个例子(重要)

 1 #include <stdio.h>
2
3 // 减法运算
4 int minus(int a, int b) {
5 return a - b;
6 }
7
8 // 加法运算
9 int sum(int a, int b) {
10 return a + b;
11 }
12
13 // 这个counting函数是用来做a和b之间的计算,至于做加法还是减法运算,由函数的第1个参数决定
14 void counting( int (*p)(int, int) , int a, int b) {
15 int result = p(a, b);
16 printf("计算结果为:%d\n", result);
17 }
18
19 int main()
20 {
21 // 进行加法运算
22 counting(sum, 6, 4);
23
24 // 进行减法运算
25 counting(minus, 6, 4);
26
27 return 0;
28 }

如果以后想再增加一种乘法运算,非常简单,根本不用修改counting函数的代码,只需要再增加一个乘法运算的函数

int mul(int a, int b) {
return a * b;
}

然后counting(mul, 6, 4);就可以进行乘法运算了

最新文章

  1. C++开始前篇,深入编译链接(补充1)
  2. 用Word收集网页中的内容,用文档结构图整理
  3. 主机控制器接口(HCI)
  4. 服务器端javascript——Rhino和Node
  5. smarty模版使用php标签,获取模版变量!
  6. Kendo UI开发教程(21): Kendo MVVM 数据绑定(十) Source
  7. iOS开发-文件操作
  8. AOJ/树二叉搜索树习题集
  9. 积累jquery一些有意思的函数
  10. user 不在 sudoers 文件中。此事将被报告。
  11. 潭州课堂25班:Ph201805201 tornado 项目 第五课 增加用户系统-用户中心(课堂笔记)
  12. 前端测试框架Jest系列教程 -- Mock Functions(模拟器)
  13. su: 无法设置用户ID: 资源暂时不可用
  14. 手机站CSS
  15. &lt;iOS&gt;一个开发中值得注意的细节
  16. UVALive-3415 Guardian of Decency (最大独立集)
  17. SC OpenService 失败5:拒绝访问
  18. Html5学习2(Html表格、Html列表、Html5新元素、Canvas (坐标、路径、画圆、文本、渐变、图像))
  19. Flask学习笔记:数据库ORM操作MySQL+pymysql/mysql-python+SQLAlchemy/Flask-SQLAlchemy
  20. 大数据学习——scala数组

热门文章

  1. java 导出数据为word文档(保持模板格式)
  2. MyCAT常用分片规则之分片枚举
  3. npm上传自己的项目
  4. 项目中遇到的Integer问题--转
  5. IOS 整体架构 和 MVC布局
  6. 30天React Native从零到IOS/Android双平台发布总结
  7. 公司的一个面试题:如何用css让一个容器水平垂直居中?
  8. angular.js写法不规范导致错误
  9. ASP.NET多种不同页面间数据传递的方法
  10. 【C#】分享带等待窗体的任务执行器一枚