C语言高手帮忙分析一下下面这个复杂的声明,最好有详细步骤:
void (*signal(int sig, void (*handler)(int)))(int);
该函数原型来自C语言标准库
signal.h
.
C语言高手帮忙分析一下下面这个复杂的声明,最好有详细步骤:
void (*signal(int sig, void (*handler)(int)))(int);
该函数原型来自C语言标准库
signal.h
.
c
void (*signal(int sig, void (*handler)(int)))(int); ^^^^^^^^^^^^^^^^^^^^^ // 是函数指针,设为 Func1 void (*signal(int sig, Func1))(int) ^^^^^^^^^^^^^^^^^^^^^^ // 是普通函数,设为 Func2 void (*Func2)(int) ^^^^^^^^^^^^^^^^^^ // 是函数指针,设为 Func3
Func1
: void(*)(int)
Func2
: signal(int, Func1)
Func3
: void(*)(int)
== Func1
于是该函数声明可简化为:
c
Func1 signal(int, Func1);
还觉得难吗?
再补充上用法吧,可能更加清楚:
c
void my_handler (int param) { signaled = 1; } void (*prev_handler)(int); // 声明一个函数指针 prev_handler = signal (SIGINT, my_handler);
应该很清楚了,该函数声明中,主体是 Func2
, 返回值与参数 2 的类型都是 Func1
.
c
变量的声明有两部分组成:类型和声明符,对声明符求值得到结果类型为给定的类型。
举个最简单的例子
int a;
a
的类型就是上述声明中指定的类型,即int
型。
同样,在来看指针和函数的声明,这里不考虑指针的初始化问题。
int * p;
int foo1(void);
int *foo2(void);
int (*foo3)(void);
*p
求值结果的类型为int
型,因此p
的类型就是指向int
型变量的指针。foo1(void)
求值结果为一个int
型数,那么foo1
就是返回值为int
型数的函数,无参数。
注意第三个声明,()
的优先级高于*
,因此*foo2(void)
可以看作*(foo2(void))
,对其求值结果为一个int
型数,那么foo2(void)
结果就是指向int
型数的指针,因此foo2
是返回值为指向int
型数指针的函数。
第四个声明中,(*foo3)(void)
求值结果是int
数,因此(*foo3)为返回值为int
数的函数,最终得出foo3
是指向这个函数的指针,即foo3
指向返回值为int
型数的函数。
上面就是基本的类型声明,不论多复杂的函数声明都是用上述的声明方式组合而来的。在分析题中的函数声明之前,再说明一下类型转换符,c
中需要强制转化一个数据类型时,在数据前加上(类型关键字)
,比如
int a;
a = (int)(1.0);
简单类型可以这样,那么复杂类型怎么做强制转化呢?其实很简单,将之前定义类型声明语句的变量名和;
去掉,再将剩余的部分还是放在一个括号中就可以了,其实也适用于简单类型。
int (*foo4)(void);
上面的声明定义了指向返回值为int
型数的函数的指针,那么该类型的类型转换符为(int (*)(void))
。
最后回到题中的函数声明。
先来分析signal
函数的参数,一个为代表信号的int
型数,一个指向信号处理函数的指针,那返回值呢?返回值就是指向信号处理函数的指针。
再来看看信号处理函数定义,参数为代表信号的int
型数,无返回值。
void sigfunc(int n)
{
/*
信号处理代码
*/
}
那么现在可以得到这个自定义的信号处理函数声明
void sigfunc(int);
怎么得到一个指向自定义的信号处理函数的指针呢?很简单,假设该指针名为pfunc
,则*pfunc
就代表了sigfunc
函数,因此指向自定义信号处理函数的指针声明为
void (*pfunc)(int);
signal
函数的返回值类型与pfunc类型相同,即pfunc
可由signal(arg1,arg2)
代替,其中arg1
和arg2
分别为代表信号的的int
型数和指向自定义信号处理函数的指针。
void (*signal(int n,void (*pfunc)(int)))(int)
将其中的变量名省略就是signal函数的声明
void (*signal(int,void (*)(int)))(int)
以上都是我自己参考<C陷阱与缺陷>中第2章而写,之前自己看过一边,在这个问题上一直没有较深理解,这次回答也相当于自己再思考一遍这个问题,希望大家指点。
这个函数:
void ( *signal( int signo, void ( *func )( int ) ) )( int );
在UNIX网络编程 volume 1(3th edition)P105页上看到过。
我的理解。
首先你得区分函数指针和指针函数,不然你看相关解释可能会晕。简单地说,函数指针指向的是一个函数;函数指针说的是这个函数的返回类型是一个指针。
void ( *func )( int )
就是一个函数指针,指向的目标函数的参数是int型,即指向的目标函数是这样的类型:void func(int)
。意思就说指向要处理信号的函数。
而void ( *signal())( int )
表明signal函数是一个指针函数,即就是返回的是一个指针。该指针指向函数,而指向的函数的类型是void func(int)
.
书上接着定义了typedef void Sigfunc( int )
那么整个函数就可以简写为:Sigfunc *signal( int signo, Sigfunc *func );
-------------------额外的---------------------
信号处理分有两种方法:
1)POSIX方法是调用sigaction函数。2)ANSI C提供的方法是signal.h中的signal()函数。
两种方法有一定得差异吧,于是就定义了自己的信号处理函数。达到的效果就是使用了POSIX函数但是却定义了简单地接口(要知道sigaction函数要三个参数还要自己分配填写结构)
希望对你有帮助 :D
signal 返回值是 void(*)(int) 类型的函数指针
void (signal(int sig, void (handler)(int)))(int);
这样声明,考虑过可读性了么,考虑过维护性了么
这已经算简单的了
void (*signal(int sig, void (*handler)(int)))(int);
下面来改写
typedef void (*Handler)(int);
typedef void (*Result)(int);
typedef Result (*Signal)(int sig, Handler handler);
已经快一年没用过C了,不知道有没有语法错误。
signal() 函数,有两个参数:
int sig
和void (*handler)(int)
返回值是
void(*)(int)
类型的函数指针