关于指针,前面文章C语言指针详解有过介绍,这里主要讨论函数指针和指针函数。

1 什么是指针?

定义:指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量;

上面一个 4GB 的内存可以存放 2^32 字节的数据。左侧连续的十六进制编号就是内存地址,每个内存地址对应一个字节的内存空间。而指针变量保存的就是这个编号,也即内存地址。

指针的声明:

指针其实就是一个变量,指针的声明方式与一般的变量声明类似,如下:

int *p;         // 声明一个 int 类型的指针 p,该指针指向一个int类型的对象
char *p         // 声明一个 char 类型的指针 p,该指针指向一个int类型的对象
int *arr[10]    // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针
int (*arr)[10]  // 声明一个数组指针,该指针指向一个 int 类型的一维数组
int **p;        // 声明一个指针 p ,该指针指向一个 int 类型的指针

声明一个指针变量并不会自动分配任何内存。在对指针进行间接访问之前,指针必须进行初始化:或是使他指向现有的内存,或者给他动态分配内存,否则我们并不知道指针指向哪儿,这个问题需要特别关注。

2 什么是函数指针?

函数指针定义:函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。

其通用表达式为:类型说明符 (*函数名) (参数)

int (*fun)(int x)  //函数指针的定义
int (*fun)(int x,int y) //函数指针的定义

函数指针在PC软件开发中使用较少,在嵌入式行业使用较多,但是无论是PC软件还是嵌入式软件,理解函数指针的定义和使用,对于理解程序设计都是很有好处的。

函数指针的赋值

函数指针和其他指针一样定义之后使用之前也是需要初始化。

函数指针有两个用途:调用函数做函数的参数

int (*fun)(int x,int y) //函数指针的定义
fun = &Function          //函数指针的赋值方式1
fun = Function           //函数指针的赋值方式2
x = (*fun)()             //函数指针的调用方式1
x = fun()                //函数指针的调用方式2

函数赋值的时候取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,并且赋值的时候函数不需要带圆括号;

如果是函数调用,还必须包含一个圆括号括起来的参数表。

函数指针的用法

我们使用指针的时候,需要通过钥匙 * 来取其指向的内存里面的值,函数指针使用也如此。通过用(*pf)取出存在这个地址上的函数,然后调用它。

char*  fun(char* p1,char* p2)
{int i = 0;i = strcmp(p1,p2);if(0 == i){return p1;}else{return p2;}
}
int main()
{char * (*pf)(char* p1,char* p2);pf = &fun;(*pf)("aa","bb");return 0;
}

这里需要注意到是,在Visual C++6.0里,给函数指针赋值时,可以用&fun或直接用函数名fun。这是因为函数名被编译之后其实就是一个地址,所以这里两种用法没有本质的差别。

用法延申

当我们不满足于函数指针上面如此简单的用法时,这时候需要一个高级用法来扩展我们对于函数指针的认知边界。

感兴趣的同学可以看看下面这个用法,并尝试理解该表达式是如何使用的函数指针。

(* (void(*)()) 0)(); //出自《C Trap and Pitfalls》这本经典的书

答案如下: ``

  • 第一步:通过void(*) (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
  • 第二步:通过(void(*) ())0,可以明白这是将0强制转换为函数指针类型,0是一个地址,也就是说一个函数存在首地址为0的一段区域内。
  • 第三步:通过(*(void(*) ())0),可以明白这是取0地址开始的一段内存里面的内容。
  • 第四步:最终理解(*(void(*) ())0)(),这是函数调用。

让程序跳转到绝对地址为0x0113F90C

方法一:

  • 0x0113F90C地址强制转换为函数指针类型,即: (void (*)())0x0113F90C
  • 然后调用:((void (*)())0x0113F90C)()

方法二:

typedef (void (*)())  VoidFuncPtr;
((VoidFuncPtr)0x0113F90C)();

面试题:指出程序的错误

#include<stdio.h>void main(void)
{int max(x,y);int *p=max;int a,b,c,d;scanf("%d %d %d",a,b,c);d=p(p(a,b),c);printf("d:%dn",d);return;
}
int max(int a,int y)
{return(x > y ?x:y);
}

答案

  • int max(x ,y);函数声明错误,改为:int max(int x,int y);

解析:max函数声明只是写出了函数的形参的名称,这对参数的类型来说是毫无意义的,编译器会把xy当做数据类型来看,编译时会出错,max的调用肯定也会出错。

  • int *p=max;指针定义错误,改为:int (*p)(int ,int)=max;

解析:函数的指针是不能直接赋值给int型指针.

  • scanf("%d %d %d",a,b,c);库函数使用错误,改为scanf("%d %d%d",&a,&b,&c);

解析:库函数使用错误,第二部分应该是接收数据的地址,这里却写成了变量。

  • d=p(p(a,b),c);函数指针调用函数错误,改为d=(*p)((*p)(a,b),c); `

解析:用函数指针调用函数的格式如下:(【*】【函数指针名称】)(【参数列表】);不能直接用函数指针加上参数就直接调用

3 什么是指针函数?

指针函数定义:指针函数的落脚点是一个函数,这个函数的返回值是一个指针,与普通函数int function(int,int)类似,只是返回的数据类型不一样而已。

_type_ *function(int, int) //返回的是指针地址
int function(int,int)     //返回的是int型数据。int  *fun(int x)        //指针函数的定义
int * fun(int x,int y)  //指针函数的定义
int* fun(int x,int y)   //指针函数的定义

以上三种写法均正确,但是*靠近返回值一点更容易理解。

指针函数的调用

在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。

typedef struct _Data{int a;int b;
}Data;//指针函数
Data* f(int a,int b){Data * data = new Data;data->a = a;data->b = b;return data;
}int main(int argc, char *argv[])
{QApplication a(argc, argv);//调用指针函数Data * myData = f(4,5);qDebug() << "f(4,5) = " << myData->a << myData->b;return a.exec();
}

不过也可以将其返回值定义为 void* 类型,在调用的时候强制转换返回值为自己想要的类型。

其输出结果是一样的,不过不建议这么使用,因为强制转换可能会带来风险。返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。

事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。

比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。

4 函数指针和指针函数的区别

通过以上的介绍,小伙伴应该都能理解二者的定义。那么简单的总结下二者的区别:

1. 定义不同

  • 指针函数本质是一个函数,其返回值为指针。
  • 函数指针本质是一个指针,其指向一个函数。

2. 写法不同

  • 指针函数:int* fun(int x,int y);
  • 函数指针:int (*fun)(int x,int y);

可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。

再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。

3. 用法不同

上面函数指针和指针函数的用法都有,但是函数指针的用法会更多,相对而言难度也更大,例如函数指针与回调函数,如果是C++非静态成员函数指针,其用法也会有一些区别,感兴趣的同学可以关注后续推文或自行查阅相关书籍。

总而言之,这两个东西很容易搞混淆,一定要深入理解其两者定义和区别,避免犯错。

c c++ 函数内数组初值_C/C++函数指针与指针函数相关推荐

  1. c c++ 函数内数组初值_C/C Plus Plus中的函数

    函数是一组语句,这些语句接受输入,进行一些特定的计算并产生输出. 其思想是将一些常见的或重复执行的任务放在一起并创建一个函数,这样我们就可以调用该函数,而不是为不同的输入一次又一次地编写相同的代码. ...

  2. c c++ 函数内数组初值_C编程基础-关键字-函数和指针

    C术语的基本定义,例如关键字,标识符,运算符,指针,数据类型,void main(),函数和递归. 在大多数情况下,我们突然无法回答一些简单的问题,例如C中的关键字是什么,C中的标识符是什么,C中的数 ...

  3. 函数c语言表示_C语言定义无参数的函数时,f()和f(void)有什么区别?

    相信C语言初学者常会在前辈留下的项目,或者一些开源项目中看到以 void 作为参数的函数,例如 void fun(void),虽然我们都明白在C语言中,"void"表示空,但是按理 ...

  4. php函数内的循环,PHP 循环列出目录内容的函数代码

    PHP 循环列出目录内容的函数代码 复制代码 代码如下: function list_files($dir) { if(is_dir($dir)) { if($handle = opendir($di ...

  5. 变量是否在数组内c语言,函数内创建的数组在调用后,是否就不存在

    函数内创建的数组在调用后,是不是就不存在 本帖最后由 test_lockxxx 于 2014-04-23 09:31:06 编辑 第1种写法: char *getABC() { char str[10 ...

  6. 函数 内置函数 动态数组 字符

    取随机数 srand(); int num = rand();//这样执行多次都是一个相同的数 如果每次都不同要每次取一个种子 所以一般与时间连用 #include<time.h> sra ...

  7. php函数从数组中取出指定的数目,PHP数组函数

    1.array_rand()从数组中随机取出一个或多个元素(返回值是:随机元素的键)$arr=['js','css',25,'php',30]; printf(' %s ',print_r($arr, ...

  8. 指针进阶(指针与数组传参、数组指针与指针数组、函数指针数组、回调函数的辨析)

    指针 指针作为C语言中极具代表性的特征之一,也是C语言学习中的一大难点. 简单来说,指针我们需了解的最基础的即: 指针是一个用来存放地址的变量,地址唯一标识一块内存空间. 指针的大小是固定的4/8个字 ...

  9. php 查找键名,array_key_exists()函数搜索数组键名步骤详解

    这次给大家带来array_key_exists()函数搜索数组键名步骤详解,array_key_exists()函数搜索数组键名的注意事项有哪些,下面就是实战案例,一起来看一下. array_key_ ...

最新文章

  1. ccat – 使用语法突出显示输出内容
  2. 汇编 DA A 十进制调整指令
  3. JS中URL编码解码
  4. 可以自发热的袜子,穿上暖3.9℃,这个冬天不再怕脚冷!
  5. 黑马ee在职进阶视频_进阶– Java EE 7前端5强
  6. wp实例开发精品文章源码推荐(8.20)
  7. arcgis交通可达性分析步骤_【规划广角】街道慢行品质的多维度评价与导控策略——基于多源城市数据的整合分析...
  8. vue 关于数组的固定随机排序
  9. Android 如何正确的获取屏幕高度
  10. OSChina 周六乱弹 ——备误操作删库,还需要你恢复!
  11. 仿京东详情页商品图片查看
  12. Strings must be encoded before hashing
  13. Spark Streaming与流处理
  14. MQTT协议——MQTTX工具使用
  15. 计算机主机和外设的接口是,外设接口
  16. form表单,账号注册实例
  17. 学生成绩管理系统-设计文档
  18. 权限如何和系统进行挂钩_将人肺与猪挂钩可以将它们保存下来进行移植
  19. 德国银行继续对数字货币持观望态度
  20. 获取本机ip和端口号

热门文章

  1. nodejs安装及环境配置(windows系统)
  2. 无插件无 Flash HTML5 浏览器直接玩《Quake II》
  3. windows给应用断网
  4. Uva1595 对称轴
  5. alpha事后诸葛亮
  6. zend studio调试
  7. SQLServer学习笔记系列6
  8. 《LeetCode力扣练习》剑指 Offer 24. 反转链表 Java
  9. Vue HTML:在Vue上写Html遇到的一些问题,html的首行缩进,html的行间距,element UI的回到顶部不显示
  10. 产生随机数的用户图形界面Python GUI