转:C语言复杂的类型声明
本文最终达到目标:读懂 ( (void(*)(void))&shellcode )() 和 int *(*func())() 是什么意思。
如果你能读懂,那甭往下看了,不会有什么收获。
关于这个问题,主要有两种方法,一种是右左法则,一种是优先级法则,我个人喜欢优先级法则(其实两者貌似是异曲同工),下面以优先级法则为例说明这个问题:
简要概述:
先从最里边的标识符开始,根据符号的优先级,来判断类型,一步一步的往外读,直到最后结束。
举例子(例子才是最好的导师):
- int (*func)();
从最里边的func开始,*表示func是一个指针类型,跳出所在的小括号,右边有()表示是一个函数,它的返回值是int类型的,综合起来读就是: func 是一个指针,它指向一个函数, 这个函数的返回值为int类型。
2. int (*func[5])();
仍然是从最里边的func开始读起(要是有形参,可以先把所有的形参去掉之后,看最关键的词,这里是func),在func的两边,[ ]的优先级高于*,所以,首先,func是一个数组,这个数组有5个元素,再看*,表示数组的元素是指针类型,此时所在( )里的内容读完,跳出,右边有( ),表示一个函数,它的返回值类型为int,综合起来:func是一个有5个元素的数组,元素类型为指针,这些指针指向函数,函数的返回值为int类型。如果你觉得不够人性化,那么做下修饰也是很简单的事情:func是一个有5个函数指针的数组,指向的函数返回值为int类型。
在这里说一点,我个人并不赞成把类型说成一句话的形式,那样让人恶心,而且迷糊。
在这里说一点,我个人并不赞成把类型说成一句话的形式,那样让人恶心,而且迷糊。
3.int (* (func)() ) [5];
从最里边的func开始读起,( ) 优先级高于*,所以首先func是一个函数,这个函数返回一个指针,[5],表示指针指向一个含有5个元素的数组,元素类型为int。可能有人要问,为什么是指向含有5个元素的数组的指针,而不是一个
一个含有5个指针的数组?这个 int (*p)[5] 好理解么?上边的不就跟这个一样嘛。
4. int (* (* (*func)() )[5] ) (); //每次读之前还是加几个空格的好
跟上边一样,去掉了不必要的形参之后我们从func读起,func所在( )只有一个*,所以(1)func首先是一个指针,跳出所在( ),右边的( )优先级高于左边的*,所以(2)func指向一个函数,(3)这个函数返回一个指针,再跳出红色的括号,[ ]优先级高于*,所以(4)函数返回的那个指针指向一个有5个元素的数组,(5)数组的元素是指针类型,再跳出紫色的括号,得(6)数组内元素的指针指向函数,(7)函数的返回值为int类型。
好了,相当的多,让我想起了以前老人常说的一句话“丈母娘的裹脚布——又臭又长”。综合以上7点,可以得到如下结论:func是一个指针,指向一个函数,这个函数返回一个指向一个具有5个元素的数组,数组的元素是为返回值为int类型的函数指针。
好了,相当的多,让我想起了以前老人常说的一句话“丈母娘的裹脚布——又臭又长”。综合以上7点,可以得到如下结论:func是一个指针,指向一个函数,这个函数返回一个指向一个具有5个元素的数组,数组的元素是为返回值为int类型的函数指针。
行文到这里我想我们已经够复杂了,其实这样的定义在现实中几乎不会出现(用“几乎”这个词是因为有时候你确实需要用到这些复杂的定义,而且有时候面试题也会出这些定义来考,很变态的说)。关于文章开头的两个定义,我想现在你应该可以读懂了。
最后,再说说最前面的两个类型声明:
( (void(*)(void))&shellcode ) ()
前一部分是要把shellcode转化为一个函数指针, 这个指针指向一个返回值为void类型的函数;然后进行函数调用。
int * ( *func() ) ()
func是一个函数, 函数的返回类型为指针,这个指针指向一个返回值为int*类型的函数