说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上手C语言。如果你还没有编程经验,或者对C语言、iOS开发不感兴趣,请忽略

前言

前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧。指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理、提升程序性能。关于指针的内容还非常多,比如指针数组、指向数组的指针、指向指针的指针,呵呵,看到这些名字是否都觉得头大了,不过我就暂时不在博客中讲解这些内容了,我只讲述在iOS开发中指针的最常见用法,比如这一章的内容----返回指针的函数与 指向函数的指针

一、返回指针的函数

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

返回指针的函数的一般形式为:类型名 * 函数名(参数列表)

比如下面这个函数,返回一个指向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 }

* 首先在第3行定义了一个sum函数,接收2个int类型的参数,返回值类型为int

* 然后在第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);就可以进行乘法运算了


【C语言】-返回指针的函数与指向函数的指针的更多相关文章

  1. 【C语言】14-返回指针的函数与指向函数的指针

    前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如 ...

  2. C++ 指针的引用和指向引用的指针

    指向引用的指针 简单使用指针的一个例子就是: int a = 1; int *p = &a; 预先强调: 没有指向引用的指针 原因: 因为引用 不是对象,没有地址. 但是指向引用的指针是什么形 ...

  3. c++不允许指向常量的指针赋值给不指向常量的指针

    #include <iostream> using namespace std; class A { public: int i; int j; } int main() { const ...

  4. 12-返回指针的函数&&指向函数的指针

    前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针   一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...

  5. C语言指向函数的指针

    定义形式:类型 (*指针变量名)(参数列表); 例如:int (*p)(int i,int j); 在这里 int是函数的返回类型,*p是指向函数的指针,(int i,int j);是函数的参数 注意 ...

  6. 《C++ Primer》之指向函数的指针

    函数指针是指指向函数而非指向对象的指针.像其他指针一样,函数指针也指向某个特定的类型.函数类型由其返回类型以及形参表确定,而与函数名无关: // pf points to function retur ...

  7. 指向函数的指针 ------ 函数指针(function pointer)

    函数指针: 指向函数的指针, 首先是一个指针, 这个指针指向一个函数. 函数具有可赋值给指针的物理内存地址,一个函数的函数名就是一个指针,它指向函数的代码.一个函数的地址是该函数的进入点,也是调用函数 ...

  8. 《征服 C 指针》摘录4:函数 与 指针

    一.指向函数的指针 函数名可以在表达式中被解读成“指向函数的指针”,因此,正如代码清单 2-2 的实验那样,写成 func 就可以取得指向函数的指针. “指向函数的指针”本质上也是指针(地址),所以可 ...

  9. [C++]数组指针,数组引用,函数指针

    数组指针是指一个指向数组的指针,例如有一个数组指针p指向一个数组a[],则 *p是取到这个数组,也就是说 *p=a,因此 **p =a[0], 它的定义为: ]; ]=&a; (*c)表示它是 ...

随机推荐

  1. @cms_content_list

    [@cms_content_list typeId='1,2,3' count='18' orderBy='4' channelId='75' channelOption='0' dateFormat ...

  2. Java NIO学习-详细内容(三)

    九.nio.file 该包是1.7新出的,包含了一系列高级的文件和目录操作方法 1.控制目录属性,只读,系统之类的 2.监控文件及文件夹的改变的WatchService public void sta ...

  3. 一些linux工具在windows版本下的文件放置位置

    首先说明一下windows下的常用变量(这里是XP的,win7及以上的C:\Documents and Settings实际为C:\Users) %SystemDrive%        操作系统所在 ...

  4. python抓网页数据【ref:http://www.1point3acres.com/bbs/thread-83337-1-1.html】

    前言:数据科学越来越火了,网页是数据很大的一个来源.最近很多人问怎么抓网页数据,据我所知,常见的编程语言(C++,java,python)都可以实现抓网页数据,甚至很多统计\计算的语言(R,Matla ...

  5. Java中String、StringBuffer和StringBuilder之间的区别

    String在Java中是字符串常量 例如 String str = "abc"; str = str + 1; System.out.println(str); 结果将是abc1 ...

  6. WEB应用从服务器主动推送的方法

    1.短轮询 2.长轮询 3.iframe 4.sse 5.Web Scoket

  7. WPF 控件库——仿制Windows10的进度条

    WPF 控件库系列博文地址: WPF 控件库——仿制Chrome的ColorPicker WPF 控件库——仿制Windows10的进度条 WPF 控件库——轮播控件 WPF 控件库——带有惯性的Sc ...

  8. CLR via C# 读书笔记-21.托管堆和垃圾回收

    前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...

  9. python3.7.0安装

    如何安装Python的操作步骤: 1.第一步先去python的官方网站下载python的安装包 地址:https://www.python.org/downloads/ 根据自己的系统选择对应的安装包 ...

  10. python列表重复判断

    import random import string n = 0; while n<10: str_source = string.ascii_letters + string.digits ...