http://blog.chinaunix.net/uid-20178794-id-1972862.html

signal函数:void (*signal(int,void(*)(int)))(int); 
2008-04-11 15:26:02

signal函数:void (*signal(int,void(*)(int)))(int)

#include <signal.h>
void (*signal (int sig, void (*func)(int)))(int);

That is to say, signal is a function that returns a pointer to another function. This second function takes a single int argument and returns void. The second argument to signal is similarly a pointer to a function returning void which takes an int argument.

这个例子来自《C陷阱与缺陷》……

signal函数是著名的信号函数,但是它的定义却非常的复杂……

任何C变量,都是由“类型”+“表达式”组成,它表示,对“表达式”求值,返回的类型,是声明给定的“类型”的值,如

 

CODE:

int a;

也就是对表达式a求值,是一个int类型;

同样地,

 

CODE:

int func();

这个声明的含义是,对表达式func()求值结果是一个int类型,也就是说,func是一个返回值是int类型的函数。

进一步,

 

CODE:

int *a;

也就是,*a是一个整型变量,那a当然就是一个指针,一个指向整型类型变量的指针;

那么,

 

CODE:

int *func();

同样地,因为()的优先级高于*,所以func是一个函数,它返回一个整型变量指向整型变量的指针;

进一步地,

 

CODE:

int (*func)();

这一回*被括号括了起来,因为*被先执行,所以,func自然地是一个指针,它指向的类型是一个函数
,即func是一个指向函数的指针,
并且,这个函数,返回一个整型变量。

另一个要讨论的问题是,如何得到一个类型指定的类型转换符,比如:
int a;
float b;
要强b转换为int类型,需要把
int a;
中的变量名去掉,然后把末尾的;去掉,再把剩余的部份用括号括起来,即:
(int)
所以,以下表达式:
int (*func)();
如果我们要得到对应的函数指针的类型转换符,则把func去掉,再把;去掉,再用括号
把剩余的部份括起来,即:

 

CODE:

(int (*)())

表示一个“指向返回值为整型类型的函数的指针”的类型转换符。

那么,如果要将常数0,转换为一个函数指针,且这个函数返回值类型为void类型,应该如何表示呢?
根据上面所说,
(void (*)())
这个也就不用再解释,那么,要强制类型转换也很简单:
(void (*)())0
现在,它已经是一个函数指针了,把它简写为fp:
#define fp (void (*)())0
要调用这个函数指针,很简单,
(*fp)()
当然,fp是一个函数指针,这样的调用形式,可以简写为
fp()
,当然,这仅仅是简写……
所以,(*fp)(),把fp这个宏展开:
就是

 

CODE:

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

这么复杂的东东,其实很简单,就是先为常数0进行类型转换,转换为一个“指向返回类型为void的函数指针”,然后
再调用它。

用typedef来简化(*(void (*)())0)():

 

CODE:

typedef void (*funcptr)();
(*(funcptr)0)();

著名的signal函数的声明,就是这样啦:

 

CODE:

void (*signal(int,void(*)(int))(int);

同样地,用typedef可以简化它:

 

CODE:

typedef void (*HANDLER)(int);
HANDLER signal(int,HANDLER);

这已经是我们习惯看到的形式了。

signal函数:void (*signal(int,void(*)(int)))(int);的更多相关文章

  1. signal函数的原型声明void (*signal(int signo, void (*fun(int))))(int)分析

    转:http://blog.sina.com.cn/s/blog_4850a7880100hnam.html void (*signal(int signo, void (*fun(int))))(i ...

  2. 如何理解这段代码:void (*signal (int sinno,void(*func)(int)))(int)

    void (*signal (int sinno,void(*func)(int)))(int) 先来看void(*func)(int)   这里的意思是声明一个函数指针func,它的参数类型为int ...

  3. signal函数理解或者void (*signal(int signum,void(*handler)(int)))(int)理解

    把void (*signal(int signum,void(*handler)(int)))(int)分成两部分: typedef void (*sighandler_t)(int); sighan ...

  4. 信号之signal函数

    UNIX系统的信号机制最简单的接口是signal函数.signal函数的功能:为指定的信号安装一个新的信号处理函数. #include <signal.h> void (*signal(i ...

  5. signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数

    信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...

  6. POSIX信号和自定义signal函数

    一.信号的概念 信号(signal)就是告知某个进程发生了某个事件的通知:信号通常是异步发生的,也就是说接受信号的进程不知道信号的准确 发生时刻:信号可以(1)由一个进程发给另一个进程:(2)由内核发 ...

  7. 三十、Linux 进程与信号——信号的概念及 signal 函数

    30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...

  8. 【VS开发】程序如何捕捉signal函数参数中指定的信号

    当说到signal的功能时,我们都知道它会捕捉我们所指定的信号,然后调用我们所指定的信号处理函数.但它是如何捕捉我们指定的信号的呢?下面我就以msdn上关于signal的example为例,说明sig ...

  9. 简单理解函数声明(以signal函数为例)

    这两天遇到一些声明比较复杂的函数,比如signal函数,那我们先简单说说signal函数的用法:(参考<c陷阱与缺陷>) [signal:几乎所有c语言程序的实现过程中都要用到signal ...

随机推荐

  1. bzoj 3123: [Sdoi2013]森林(45分暴力)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4184  Solved: 1235[Submit][Status ...

  2. bzoj4873: [Shoi2017]寿司餐厅(最小割)

    传送门 大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里 1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值 ...

  3. Spring MVC 基于Method的映射规则(注解版)

    在Restful风格的web开发中,根据不同的请求方法使用相应的控制器处理逻辑成为核心需求,下面就看看如何在Spring MVC中识别不同的请求方法. 请求方法 在Http中,请求的方法有很多种,最常 ...

  4. jmeter 签名MD5生成(转)

    请求接口需要同时发送签名,签名定义为: 可以看出签名就是把用户的密码 .用户名 和签名key生成一个md5串就可以了 刚好jmeter 有个md5 生成,生成前需要获取name ,password k ...

  5. Observer模式(观察者设计模式)

    Observer 设计模式? 在Observer模式中,当观察对象的状态发生变化时,会通知给观察者.Observer模式适用于根据对象状态进行相应处理的场景. Observer 并非主动观察,而是被动 ...

  6. 外键约束 foreign key

    外键约束 :保持数据一致性,完整性实现一对多关系.外键必须关联到键上面去,一般情况是,关联到另一张表的主键 (因为一个表只存一类信息.用外键来做参照,保证数据的一致性,可以减少数据冗余) ##表acr ...

  7. [Leetcode]005. Longest Palindromic Substring

    public String longestPalindrome(String s) { int start = 0, end = 0; for (int i = 0; i < s.length( ...

  8. Java多线程与并发——死锁与中断线程

    过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现. 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁. 死锁例子: package com.vince; /** ...

  9. 用 Java 实现断点续传参考 (HTTP)

    断点续传的原理 其实断点续传的原理很简单,就是在 Http 的请求上和一般的下载有所不同而已.        打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:        假设服务器域名为 ...

  10. C# 多线程之线程池

    线程池System.Threading.ThreadPool,可用于发送工作项.处理异步I/O.代表其它线程等待以及处理计时器.基本用法: public void Main() { ThreadPoo ...