转:关于"复杂类型声明"的分析方法

来源:互联网 发布:灵玖软件 编辑:程序博客网 时间:2024/05/20 16:36
关于"复杂类型声明"的分析方法
小科 发表于 2006-8-11 20:15:00

今天看了一个博友的帖子,是关于复杂类型声明的;于是便一起复习了一下;
做了个总结;个人感觉这个方法能够分析任何复杂类型的声明;
复杂类型的声明主要涉及各种类型的指针,如果没有指针那么估计就没有什么
复杂的类型了.由于本人水平有限,还请各位大虾多多指教.

首先看以下最基本的==============================================>

1.看一个变量是否是指针:

 如果变量左边紧跟*;并且用括号和变量相结合,
那边它是指针;否则它不是;例如:
(int*)array[10]   array是指针数组,不是指针;
int (*array)[10]    array是数组指针.
---------------------------------------------------------------------------
(int *)fun()      fun 是函数
int (*fun)()        fun 是函数指针
------------------------------------------------------------------------
int *a            a是指针;
(int *)a          a 的类型未知,这里把a强制转换成指针

实际上指针数组,数组指针都表示一个地址,可以把数组名赋值给数组指针;
他们区别在于,数组名地址固定,而数组指针则可以指向任何同类型的数组;

函数指针和函数名也有类似关系;函数指针可以随便指,函数名却是一个固定地址.

2.形式上区别:

(TYPE)(*array)[SIZE]---------------------------->A
array是一个数组指针,指向数组(TYPE)ArrayName[SIZE]

(TYPE)array[SIZE]  ---------------------------->B
array是一个数组
----------------------------------------------------------------------------------
(RET TYPE)(*fun)(PARAM)------------------------->C
fun是函数指针,指向函数(RET TYPE)FuncName(PARAM)

(RET TYPE)fun(PARAM)  ------------------------->D
fun是函数

3.复杂类型分析方法:

  以声明的变量为中心,从右到左,从里到外;依次匹配上面A,B,C,D四个样式;
分析完毕清理;适当添加变量;下面结合具体的例子分析.

4.举例:

(1) int*( * (*gopher)( int(*)(int*) ) )(int*);

首先以声明变量gopher为中心;由于它左边紧跟一个*,并且有括号使之和变量结合因此它是一个指针;这符合A,C是个样式,
再向右看,右边是圆括号,显然符合C样式,说明这是一个函数指针;
右边括号中的是参数,剩下的是返回类型;
再看右边括号中的函数参数int(*)(int*),为了和样式对照,
我们添加适当的变量让其变成int(*a)(int*b),显然这符合样式C;说明参数a 是一个函数指针,
指向的函数参数是一个int 指针;返回值是int;
我们把分析完毕的部分(*gopher)( int(*)(int*)去掉,剩下了int*( * )(int*),这剩余的部分是
gopher指向函数的返回值,我们适当添加变量变为int*( *a)(int*b);这显然又符合样式C;
说明返回值a也是一个函数指针;其指向函数的参数是一个int 指针;返回值也是一个int 指针;

综上所述,gopher是一个函数指针,指向函数(1);
函数(1)的参数是一个函数(2)指针,返回值是一个函数(3)指针,
函数(2)的参数是int*,返回值是int;
函数(3)的参数是int*,返回值也是int*。

用typedef定义这个 gopher:
typedef int*( * (*gopher)( int(*)(int*)) )(int*);
以后用gopher fun1声明,则fun1就是和gopher类型一致的函数指针了。


(2)typedef double ( * (*(*fp3)())[10] )();

首先以变量fp3为中心,由于它左边紧跟一个*,因此它是一个指针;这符合A,C是个样式,
再向右看,右边是圆括号,显然符合C样式,说明这是一个函数指针;
右边括号中的是参数,剩下的是返回类型;
再看右边括号中的函数参数为空,也就是void类型的参数;
我们把分析完毕的(*fp3)()去掉剩下double ( * (*)[10] )();适当添加变量变为double ( *(*b)[10] )();
由于b左边紧跟一个*,因此它是一个指针;这符合A,C是个样式,
再向右看,右边是方括号,显然符合A样式,说明返回值b是一个数组指针;它指向一个数组;
那么数组中的元素是什么类型呢?我们去掉分析完毕的(*b)[10];剩下了double ( * )();
添加变量变为double ( *a)();这显然是C的样式,说明数组中的元素是函数指针,指向的函数参数为空;
返回值为double;

综上所述:fp3是一个函数(1)指针,该函数(1)没有参数,返回一个指针,
该指针是指向一个数组,这个数组“含有10个指向函数(2)的指针” ,
函数(2)不接受参,数,返回一个double值.

看上去分析很麻烦,其实分析多了不必完全按照上面的步骤进行也就很容易看懂了:)
下面是两个例子,自己分析一下吧:)

(3) void*  (*(*fp1)(int))[10];
fp1是一个函数指针,该函数接受一个整型参数,返回一个指针(前面多加一个*),
该指针指向含有10个void指针数组
如果分开写:
typedef (void**)FUN(int);
void** ppvoid = new void*[10];

(4)int (* ((*f4())[10]))(); 类似与上面的问题
f4是一个函数,返回一个指针,该指针指向含有10个函数指针的数组,这些函数返回int