`
standalone
  • 浏览: 593730 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

理解UNIX系统的signal函数的定义

    博客分类:
  • c++
阅读更多

读《 unix 环境高级编程》信号机制一章,遇到 signal 函数:

#include<signal.h>

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

返回值:成功返回信号以前的处理配置,出错返回 SIG_ERR.

 

这个定义比较复杂,按照“右左法则”来理解:

右左法则 ”[ 重要!!! ]

The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

这是一个简单的法则,但能让你准确理解所有的声明。这个法则运用如下:从最内部的括号开始阅读声明,向右看,然后向左看。当你碰到一个括号时就调转阅读的方向。括号内的所有内容都分析完毕就跳出括号的范围。这样继续,直到整个声明都被分析完毕。对上述 右左法则 做一个小小的修正:当你第一次开始阅读声明的时候,你必须从变量名开始,而不是从最内部的括号。

 

signal 函数,阅读步骤:

  1. func 开始 -----------------------------------------------func
  2. 向右看碰到)因此向左看碰到一个 *-------------------------- 一个指针
  3. 跳出括号,碰到( int --------------------------------------------------------- 一个带一个 int 类型参数的函数
  4. 向左看, int signo ------------------------------------------------------------ 又一个 int 类型的参数
  5. 红色部分处理完跳出括号向右看遇到)向左遇到 *-------------------- signal 函数)返回一个指针
  6. 粗体部分看完了跳出向右遇到( int -------------------------------------- 一个带 int 类型参数的函数
  7. 向左看发现 void-------------------------------------------------------------------void 类型, signal 函数返回的指针指向一个参数为 int 类型,返回值为 void 类型的函数。

 

可以理解为 signal 函数的参数有两个,一个是 int 类型,一个是一个函数指针(参数类型为 int ,返回值为 void ),返回值为一个函数指针(参数类型为 int ,返回值为 void )。

因此按照书中的解释,如果使用 typedef 更好理解一些:

typedef  void SigFunc ( int );   // 声明一个类型,该类型为函数且有一个 int 参数并且返回值为 void 型。

signal 函数可以简写为:

SigFunc * signal int SigFunc* );

 

关于理解复杂的 c++ 声明,这上面的左右法则是从 http://buaadallas.blog.51cto.com/399160/80947 学来的,上面有几个更复杂的声明:

下面结合例子来演示一下 右左法则 的使用。

int * (* (*fp1) (int) ) [10];

阅读步骤:
1.
从变量名开始 -------------------------------------------- fp1
2.
往右看,什么也没有,碰到了 ) ,因此往左看,碰到一个 * ------ 一个指针
3.
跳出括号,碰到了 (int) ----------------------------------- 一个带一个 int 参数的函数
4.
向左看,发现一个 * --------------------------------------- (函数)返回一个指针
5.
跳出括号,向右看,碰到 [10] ------------------------------ 一个 10 元素的数组
6.
向左看,发现一个 * --------------------------------------- 指针
7.
向左看,发现 int ----------------------------------------- int 类型


总结: fp1 被声明成为一个函数的指针 , 该函数返回指向指针数组的指针 .


再来看一个例子:

int *( *( *arr[5])())();

阅读步骤:
1.
从变量名开始 -------------------------------------------- arr
2.
往右看,发现是一个数组 ---------------------------------- 一个 5 元素的数组
3.
向左看,发现一个 * --------------------------------------- 指针
4.
跳出括号,向右看,发现 () -------------------------------- 不带参数的函数
5.
向左看,碰到 * ------------------------------------------- (函数)返回一个指针
6.
跳出括号,向右发现 () ------------------------------------ 不带参数的函数
7.
向左,发现 * --------------------------------------------- (函数)返回一个指针
8.
继续向左,发现 int --------------------------------------- int 类型

//arr is an array of 5 pointers to functions
//that take no arguments and return pointers to
//functions having no arguments and having int type as return value.

还有更多的例子:

float ( * ( *b()) [] )();     // b is a function that returns a
            // pointer to an array of pointers
            // to functions returning floats.

void * ( *c) ( char, int (*)());   // c is a pointer to a function that takes
            // two parameters:
            //   a char and a pointer to a
            //   function that takes no
            //   parameters and returns
            //   an int
            // and returns a pointer to void.

void ** (*d) (int &, char **(*)(char *, char **));   // d is a pointer to a function that takes
            // two parameters:
            //   a reference to an int and a pointer
            //   to a function that takes two parameters:
            //   a pointer to a char and a pointer
            //   to a pointer to a char
            //   and returns a pointer to a pointer
            //   to a char
            // and returns a pointer to a pointer to void

float ( * ( * e[10]) (int &) ) [5];      

            // e is an array of 10 pointers to
            // functions that take a single
            // reference to an int as an argument
            // and return pointers to
            // an array of 5 floats.本文出自 51CTO.COM 技术博客
    

分享到:
评论
1 楼 szh2048 2012-07-18  
太复杂了,看的头痛。怎么办啊。玩程序的都不是人啊。

相关推荐

    对Python信号处理模块signal详解

    Python中对信号处理的模块主要是使用signal模块,但signal主要是针对Unix系统,所以在Windows平台上Python不能很好的发挥信号处理的功能。 要查看Python中的信号量,可以使用dir(signal)来查看。 signal.signal() 在...

    操作系统实验

    首先定义一个服务函数function(),然后利用signal(sig,function)系统调用来实现中断的捕获与改道。 (5)使用操作系统保留给用户的信号SIGUSR1和SIGUSR2进行通信。 (6)扩展程序,使之成为信号或事件驱动的应用程序。 ...

    C语言基础教程TXT

    第8章 UNIX系统界面 8.1 文件描述符 8.2 低级I/O—read和write系统调用 8.3 open、creat、close和unlink系统调用 8.4 随机访问—lseek系统调用 8.5 实例—fopen和getc函数的一种实现 方法 8.6 实例—目录显示 ...

    C程序设计语言 很适合初学者和再学者学习和复习

    第8章 UNIX系统界面 8.1 文件描述符 8.2 低级I/O—read和write系统调用 8.3 open、creat、close和unlink系统调用 8.4 随机访问—lseek系统调用 8.5 实例—fopen和getc函数的一种实现 方法 8.6 实例—目录显示 ...

    c语言设计Brian W. Kernighan Dennis M. Ritchie

    第8章 UNIX系统界面 8.1 文件描述符 8.2 低级I/O—read和write系统调用 8.3 open、creat、close和unlink系统调用 8.4 随机访问—lseek系统调用 8.5 实例—fopen和getc函数的一种实现 方法 8.6 实例—目录显示 ...

    C程序设计语言(第2版·新版)

    第8章 UNIX系统界面 8.1 文件描述符 8.2 低级I/O—read和write系统调用 8.3 open、creat、close和unlink系统调用 8.4 随机访问—lseek系统调用 8.5 实例—fopen和getc函数的一种实现 方法 8.6 实例—目录显示 ...

    c程序设计语言入门基础 @精品@ 花我一年才从众书中筛选出的

    第8章 UNIX系统界面 8.1 文件描述符 8.2 低级I/O—read和write系统调用 8.3 open、creat、close和unlink系统调用 8.4 随机访问—lseek系统调用 8.5 实例—fopen和getc函数的一种实现 方法 8.6 实例—目录显示 ...

    C语言程序设计标准教程

    其中FILE应为大写,它实际上是由系统定义的一个结构, 该结构中含有文件名、文件状态和文件当前位置等信息。 在编写源程序时不必关心FILE结构的细节。例如:FILE *fp; 表示fp是指向FILE结构的指针变量,通过fp ...

    C语言精典版本C程序设计语言

    它是要对于程序员来说容易理解,而不是提供给编译器实现者的定义—这正是标准承担的角色。附录B是对标准库提供的功能的总结。附录C是对以前版本的变动的小结。就像我们在第1版序中所说的,“当对C的经验增加时它显得...

    图片预览器

    信号处理器的创建函数定义如下: gint gtk_signal_connect( GtkObject *object, gchar *name,GtkSignalFunc callback_func, gpointer func_data ); 返回值是一个区分同一对象中的事件与不同回调函数的关联标签。这样...

    linux内核 0.11版本源码 带中文注释

    其中最主要定义了tm 结构和一些有关时间的函数原形。 /* * we need this inline - forking from kernel space will result * in NO COPY ON WRITE (!!!), until an execve is executed. This * is no problem, ...

    ARM_Linux启动分析.pdf

    7- 9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。 initdefault是一个特殊的...

    Linux进程间通信–使用信号

    信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。但它们还可以作为进程间通信或修改行为的一种方式,明确地由一个进程发送给另一个进程...

    一个进程池的服务器程序

    #include &lt;signal.h&gt; #include #include #include #include #include #define PRECHILD 5 #define MAXCHILD 50 #define BUFSIZE 4096 #define PIDPATH "pid" #define head503 ...

    精通websphere MQ

    进程定义 (Process)............................................................................. 27 1.2.8 认证信息 (Auth Info)............................................................................

Global site tag (gtag.js) - Google Analytics