在《C陷阱与缺陷》第二章中,书中给出了一个问题:硬件要调用首地址为0的函数。
先不管这个问题。首先从函数指针的声明开始看。函数指针的声明:类型 (* 名称) (); 例如:int (* funptr) (); 这个表达式声明了一个函数指针funptr,funptr指向了一个返回值为int类型的函数。看这个声明的时候,可以这样看,先把后面的括号移到int后面,也就是说变成这样:int() (*funptr); 因为()是一个函数类型声明,加上int,就说明int() 是一个返回值为int的函数类型。设int()为type_1, 然后函数指针的声明就变成了type_1 *funptr; 所以funptr是一个指针类型的标识符,它指向了type_1这个类型。而这个type_1类型又是一个返回值为int的函数类型,所以funptr就是一个指向了返回值为int类型的函数的指针。当把funptr去掉,就变成了int (*) (); 分析还是一样的,它表示的是一个指向返回值为int类型的函数的指针的类型。
好,现在硬件要调用首地址为0的函数。在普通调用函数的时候,通常是函数名字加上括号,例如:fun()。但是现在是只知道函数的地址,这样做肯定不行。但是既然知道了地址整形数0,可以把0做个类型转换,转换成为一个函数指针类型。为什么要类型转换呢?在使用函数指针的时候,如果fp是一个函数指针,在调用的时候,是(*fp)()。但是, (*0)(),但是这个并不能生效。因为*要一个指针来作为操作数。这时,只要做个类型转换就可以了。那么,像上一段所说的,首先有这个void (*fp)(); 这个声明,然后去掉fp,也即是void (*) (),它是一个指向返回值为void的函数的类型的指针的类型。然后把0做个强制类型转换,void (*) () 0,有了这个函数指针,就可以完成调用了。也就是 (* void (*) () ) 0) ()