引子
(了解函数指针的构造可以不用看引子)
已知
返回类型 函数名(参数)构成函数的组成部分
(例: int Add (int x) )
而函数指针需要在函数名的左上角加上*
因为*的优先级较低,p并不会先于*结合,
所以需要用括号将p与*结合
现在就开始理解复杂的申明与定义了
第一种
那么这该如何理解呢?
首先我们把最明显的结构拿出来
void(*)()为一个 返回类型void 参数为无 的函数指针类型
注意它此时只代表类型,并没有申明,因为此时的(*)这里面没有p
在这个指针类型外面还有一个大括号,而且还有个0在右边
(void(*)())0 此时就是强制类型转换 将0转化为void(*)()函数指针类型
此时0是指针,将他解应用 *( void(*)() )0 则代表的是0所指向的函数
现在它所代表的是函数了
可为什么函数前面没有返回类型?
证明它 并不是申明!!!而是调用!!!
只有申明的时候才需要写返回类型
此时最后一个()则代表 调用这个函数 需要传的参数
此时()为无 则表示调用这个函数,但并不会进行传参
所以以上代码是一次函数调用,调用的是0作为地址所指的的函数
第二种
那么这又该如何理解呢?
首先我们把最明显的结构拿出来
void(*)(int)为一个 返回类型void 参数为int类型 的函数指针类型
再往外看int,void(*)(int) 似乎为“并列关系”
再往外看signal和*并没打括号 此时signal应该与右边的括号结合
所以signal并不会是指针 而是 函数名 + 一个参数为int类型 和 一个参数为void(*)(int)类型
再往外看 又有一个void(* )(int) 这代表的是类型
所以这个函数的返回值也是void(*)(int)类型
这样一切都解释得通了
所以这是申明
声明的signal函数的第一参数的类型为int,第二个参数类型是函数指针,
该函数指针指向的函数参数是int,返回类型是void,
signal函数的返回类型也是一个函数指针,该函数指针指向的函数参数是int,返回类型是void
展拓
我们会发现第二种有两个void(*)(int)类型
可以把这个类型重命名(typedef) 则更容易理解 又或是更容易书写
void(*)(int)类型转成另一个符号表示则只需typedef 和 在(*)里面加上想转化的符号就行
总结
我们只需要先看其内部构造,从小范围观察,再逐步往外范围扩大,
过程中,
要不断思考它是否是指针?它是否具有指针的特性和构造特点?
又是否是函数,那他的返回类型和参数是什么?
如果是调用,那我是不是可以不考虑返回类型?
等一些列问题
不断利用它们的各不相同的构造特点,排除或者确定类型,就可以了,熟能生巧。