关于"复杂类型声明"的分析方法
2007-09-06 08:18
344 查看
今天看了一个博友的帖子,是关于复杂类型声明的;于是便一起复习了一下;
做了个总结;个人感觉这个方法能够分析任何复杂类型的声明;
复杂类型的声明主要涉及各种类型的指针,如果没有指针那么估计就没有什么
复杂的类型了.由于本人水平有限,还请各位大虾多多指教.
首先看以下最基本的==============================================>
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
做了个总结;个人感觉这个方法能够分析任何复杂类型的声明;
复杂类型的声明主要涉及各种类型的指针,如果没有指针那么估计就没有什么
复杂的类型了.由于本人水平有限,还请各位大虾多多指教.
首先看以下最基本的==============================================>
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
相关文章推荐
- 转:关于"复杂类型声明"的分析方法
- [译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)
- [译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)
- .NET下编译C++代码时出现"error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int"错误的解决方法。
- LeetCode "Palindrome Partitioning"算法时间复杂度分析
- 使用控件时提示"未声明标识符"的解决方法
- FFmpeg 错误 C4996: "avcodec_alloc_frame"或者"av_free_packet"等函数被声明为已否决的解决方法
- 关于"该主机 CPU 类型不支持虚拟化性能计数器"的解决方案
- Java学习之数组1(1.数组的声明;2.元素为引用数据类型的数组;3.关于main方法里的String[] args;4.数组排序;5.数3退1 数组算法,(用数组模拟链表);6数组查找之二分法;7数组的拷贝)
- vs2003 提示"确保已安装项目类型(.vcproj)的应用程序" 的解决方法
- 关于c# 引发了"system.indexOutofRangeException"类型异常,该怎么处理
- 使用控件时提示"未声明标识符"的解决方法
- 商务随需应变与用例分析方法--网友关于工作流类型应用的建模方法问题的回复
- "getline" bug fix for Microsoft Visual C++ 6.0 关于VC6的getline输入需要两个回车才结束的BUG修改方法
- 关于Visual Studio "当前不会命中断点.还没有为该文档加载任何符号"的解决方法
- 评"软件工程项目管理:功能点分析方法与实践"
- 关于在DataTable中执行DataTable.Select("条件")返回DataTable的解决方法
- 关于"建立空文档失败"的问题的分析!(转载)
- Document root element "beans", must match DOCTYPE root "null"分析及解决方法
- 关于"多态"static方法的理解