C语言高手帮忙分析一下下面这个复杂的声明,最好有详细步骤:
void (signal(int sig, void (handler)(int)))(int);
该函数原型来自C语言标准库 signal.h.
在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:
image
规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:
image
本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:
void (*handler)(int):
① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。
② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。
③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。
void (signal(int sig, void (handler)(int)))(int):
void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:
① signal右边是圆括号,因而signal()是一个返回**的函数。
② signal()的左边是,因而signal()是一个返回指向*的指针的函数。
③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。
④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。
以上的分析过程可能有错漏,请各位看官多指教。
在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:
image
规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:
image
本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:
void (*handler)(int):
① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。
② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。
③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。
void (signal(int sig, void (handler)(int)))(int):
void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:
① signal右边是圆括号,因而signal()是一个返回**的函数。
② signal()的左边是,因而signal()是一个返回指向*的指针的函数。
③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。
④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。
以上的分析过程可能有错漏,请各位看官多指教。
C++/C并不是一门函数语言,函数也无法作为一等公民在这语言中出现,所以Cpp/C在传递参数为函数时(实际上传递的是函数的内存地址),都会将函数原型(函数名、参数)一并传入
在对上面的例子作分析之前,我们需要了解C语言的声明优先级,《C专家编程》P64原文如下:
image
规则A规定了要按照优先级来解释声明(算是一句废话)。规则C请参照本人上一篇笔记:http://www.cnblogs.com/deyuanqin/p/5705967.html。规则B的具体实践过程如下图:
image
本着抛砖引玉的目的,我们使用以上规则分析void (signal(int sig, void (handler)(int)))(int)这个复杂的声明。从易到难的顺序:
void (*handler)(int):
① handler右边是圆括号,所以handler不是数组或者函数。再看其左边,是(星号),所以handler是一个指向*的指针。
② (handler)(int)。(handler)的右边是圆括号,因而(handler)(int)中的()(int)是一个返回的函数。结合上一步分析,handler是一个指向返回*的函数的指针。
③ (*handler)(int)的右边没有符号,左边是void。综上,handler是一个指向返回void值的函数的指针。
void (signal(int sig, void (handler)(int)))(int):
void (handler)(int)在上面的步骤已经做了分析,我们可以使用语句typedef void (handler)(int)将其简化(将handler声明为一个新的类型,这个类型是是一个指向返回void值的函数的指针。有关typedef的知识改日再做分析),则void (signal(int sig, void (handler)(int)))(int)就被简化为void (signal(int sig, handle h))(int)。下面我们对void (signal(int sig, handle h))(int)作分析:
① signal右边是圆括号,因而signal()是一个返回**的函数。
② signal()的左边是,因而signal()是一个返回指向*的指针的函数。
③ (signal(int sig, handle h))右边是圆括号,因此(signal(int sig, handle h))(int)是一个返回的函数。综上,signal是一个返回指向返回函数的指针的函数。
④ (*signal(int sig, handle h))右边是void。因而,signal(这个标识符)是一个返回指向返回void值的函数的指针的函数。
以上的分析过程可能有错漏,请各位看官多指教。
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
于是该函数声明可简化为:
Func1 signal(int, Func1);
还觉得难吗?
再补充上用法吧,可能更加清楚:
void my_handler (int param)
{
signaled = 1;
}
void (*prev_handler)(int); // 声明一个函数指针
prev_handler = signal (SIGINT, my_handler);
应该很清楚了,该函数声明中,主体是 Func2, 返回值与参数 2 的类型都是 Func1.
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。