关于c++:还搞不懂C语言中的函数指针看完你就明白了

4次阅读

共计 3546 个字符,预计需要花费 9 分钟才能阅读完成。

1. 函数指针的定义

顾名思义,函数指针就是函数的指针。它是一个指针,指向一个函数。看例子:

A) char * (*fun1)(char * p1,char * p2);

B) char * *fun2(char * p1,char * p2);

C) char * fun3(char * p1,char * p2);

看看下面三个表达式别离是什么意思?

C)这很容易,fun3 是函数名,p1,p2 是参数,其类型为 char 型,函数的返回值为 char 类型。
B) 也很简略,与 C)表达式相比,惟一不同的就是函数的返回值类型为 char**,是个二级指针。
A) fun1 是函数名吗?回顾一下后面解说数组指针时的情景。咱们说数组指针这么定义或者更清晰:

int (*)[10] p;

再看看 A)表达式与这里何其相似!明确了吧。这里 fun1 不是什么函数名,而是一个指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指针。同样,咱们把这个表达式改写一下:

char * (*)(char * p1,char * p2) fun1;

这样子是不是难看一些呢?只惋惜编译器不这么想。^_^。

2. 函数指针应用的例子

下面咱们定义了一个函数指针,但如何来应用它呢?先看如下例子:

#include <stdio.h>

#include <string.h>



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。这是因为函数名被编译之后其实就是一个地址,所以这里两种用法没有实质的差异。这个例子很简略,就不再具体探讨了。咱们应用指针的时候,须要通过钥匙(“”)来取其指向的内存外面的值,函数指针应用也如此。通过用 (pf) 取出存在这个地址上的函数,而后调用它。

3.(int)&p —- 这是什么?

兴许下面的例子过于简略,咱们看看上面的例子:

void Function()

{printf("Call Function!n");

}<br>

int main()

{void (*p)();

  *(int*)&p=(int)Function;

  (*p)();

  return 0;

} 

这是在干什么?(int)&p=(int)Function; 示意什么意思?
别急,先看这行代码:

void (*p)();

这行代码定义了一个指针变量 p,p 指向一个函数,这个函数的参数和返回值都是 void。
&p 是求指针变量 p 自身的地址,这是一个 32 位的二进制常数(32 位零碎)。
(int*)&p 示意将地址强制转换成指向 int 类型数据的指针。
(int)Function 示意将函数的入口地址强制转换成 int 类型的数据。
剖析到这里,置信你曾经明确(int)&p=(int)Function; 示意将函数的入口地址赋值给指针变量 p。

那么(*p) (); 就是示意对函数的调用。

解说到这里,置信你曾经明确了。其实函数指针与一般指针没什么差异,只是指向的内容不同而已。
应用函数指针的益处在于,能够将实现同一性能的多个模块对立起来标识,这样一来更容易前期的保护,系统结构更加清晰。或者演绎为:便于分层设计、利于零碎形象、升高耦合度以及使接口与实现离开。

举荐一下本人的 linuxC/C++ 交换群:973961276!整顿了一些集体感觉比拟好的学习书籍、视频材料以及大厂面经视频共享在群文件外面,有须要的小伙伴能够自行添加哦!~

4.((void() ())0)()—— 这是什么?

是不是感觉下面的例子太简略,不够刺激?好,那就来点刺激的,看上面这个例子:

(*(void(*) ())0)();

这是《C Traps and Pitfalls》这本经典的书中的一个例子。没有发狂吧?上面咱们就来剖析剖析:

第一步:void(*) (),能够明确这是一个函数指针类型。这个函数没有参数,没有返回值。第二步:(void(*) ())0,这是将 0 强制转换为函数指针类型,0 是一个地址,也就是说一个函数存在首地址为 0 的一段区域内。第三步:(*(void(*) ())0),这是取 0 地址开始的一段内存外面的内容,其内容就是保留在首地址为 0 的一段区域内的函数。第四步:(*(void(*) ())0)(),这是函数调用。

如同还是很简略是吧,下面的例子再改写改写:

(*(char**(*) (char **,char **))0) (char **,char **);

如果没有下面的剖析,肯怕不容易把这个表达式看明确吧。不过当初应该是很简略的一件事了。读者认为呢?

5. 函数指针数组

当初咱们分明表达式

char * (*pf)(char * p);

定义的是一个函数指针 pf。既然 pf 是一个指针,那就能够贮存在一个数组里。把上式批改一下:

char * (*pf[3])(char * p);

这是定义一个函数指针数组。

它是一个数组,数组名为 pf,数组内存储了 3 个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。

这念起来仿佛有点拗口。不过不要紧,要害是你明确这是一个指针数组,是数组。函数指针数组怎么应用呢?这里也给出一个非常简单的例子,只有真正把握了应用办法,再简单的问题都能够应答。

如下:

#include <stdio.h>

#include <string.h>

<br>char * fun1(char * p)

{printf("%sn",p);

  return p;

}

char * fun2(char * p)

{printf("%sn",p);

  return p;

}

char * fun3(char * p)

{printf("%sn",p);

  return p;

}

<br>int main()

{char * (*pf[3])(char * p);

  pf[0] = fun1; // 能够间接用函数名

  pf[1] = &fun2; // 能够用函数名加上取地址符

  pf[2] = &fun3;<br>

  pf[0]("fun1");

  pf[0]("fun2");

  pf[0]("fun3");

  return 0;

} 

6. 函数指针数组的指针

看着这个题目没发狂吧?函数指针就够个别初学者折腾了,函数指针数组就更加麻烦,当初的函数指针数组指针就更难了解了。
其实,没这么简单。后面具体探讨过数组指针的问题,这里的函数指针数组指针不就是一个指针嘛。只不过这个指针指向一个数组,这个数组外面存的都是指向函数的指针。仅此而已。

上面就定义一个简略的函数指针数组指针:

1

char  ((pf)[3])(char  p);

留神,这里的 pf 和上一节的 pf 就齐全是两码事了。上一节的 pf 并非指针,而是一个数组名;这里的 pf 的确是实实在在的指针。这个指针指向一个蕴含了 3 个元素的数组;这个数字外面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。

这比上一节的函数指针数组更拗口。其实你不必管这么多,明确这是一个指针就 ok 了。其用法与后面讲的数组指针没有差异。上面列一个简略的例子:

#include <stdio.h>

#include <string.h>



char * fun1(char * p)

{printf("%sn",p);

    return p;

}



char * fun2(char * p)

{printf("%sn",p);

    return p;

}



char * fun3(char * p)

{printf("%sn",p);

    return p;

}



int main()

{char * (*a[3])(char * p);

    char * (*(*pf)[3])(char * p);

    pf = &a;



    a[0] = fun1;

    a[1] = &fun2;

    a[2] = &fun3;



    pf[0][0]("fun1");

    pf[0][1]("fun2");

    pf[0][2]("fun3");

    return 0;

}


本篇文章就到这里了,学习中有什么纳闷或者须要什么材料,能够来跟大家一起交换哦!

c/c++ 零根底小白到企业级我的项目实战

正文完
 0