让你费解的函数原型 - Linux 下的 signal - 函数指针


做Linux下软件开发的对signal函数应该不会陌生,但是你看过它的函数原型吗?如果你看了,你懂它了吗。要是有疑问,来看看我的解释吧。

先说说signal函数是干嘛的。

signal函数用于向系统注册处理某一信号的函数,说白了,就是告诉系统,当某个信号发生了,执行这个函数。

当signal被调用时,它返回调用前处理同意信号的函数的指针。

在signal.h头文件中,它的声明如下:

  1. void (*signal (int sig_num, void (*handler)(int))) (int)        

第一次看到这么一个东西,我一下子懵了,我真不知道,还有这样的函数定义。

现在就让我们一起,一步一步、一层一层地剥掉它的小括号。

前面说到,signal函数返回值是函数指针(如果不太清楚函数指针,可以先到文章的后半部分看看,也可以看看我的另一篇关于函数指针的文章),这个指针指向的函数的签名如下:

  1. void (*fp) (int)      //pointer to a function  

函数签名本不包含返回值类型的,但是函数指针记录了此信息。

对应到上面的函数原型,这里的 fp 相当于

  1. signal (int sig_num, void (*handler)(int))  

到这里,我们找出了函数的返回值类型,上面的这段看上去就亲切得多了,这就是我们平时所说的函数签名了。

函数名signal,参数列表包括一个整型值和一个函数指针。又是一个函数指针,你发现了吗,这个函数指针:

  1. void (*handler)(int)  

和上面的那个函数指针其实是一样的,其实这不难理解,因为signal函数的返回值就是信号处理函数的地址。

好了,现在的signal看着没那么可怕了。接着用吧…… 

关于函数指针

函数指针是一类特殊的指针,它存储的是函数的入口地址,也就是说,通过这个指针,你可以调用函数。

函数指针对其可以指向的函数的签名和返回值类型有严格的要求,否则,无法将某个函数地址赋给一个函数指针,举个例子。

  1. //定义一个可以指向返回值为void,参数为两个int型的函数指针,   
  2. //注意这里的*和()的位置,很重要   
  3. void (*fp)(intint)    

如果某个函数的原型是void function(int a, int b),则可以进行如下赋值和调用:

  1. fp = function;  //函数名不接括号和参数即表示此函数的地址   
  2. function (5,6);  
  3. fp(5,6);       //这与上面的function(5,6)调用具有同样的效果  

还有一个很大的不同,普通的指针可以进行强制类型转换,但是函数指针不可以。

说了这么多,到底函数指针有什么用途呢,我想典型的用处是动态调用具有相同签名和返回值的不同函数,即在不同的条件下,调用不同的函数。

(待续……稍后会附上一个简单的例子)

结束……希望对大家有用微笑

相关内容