现在的位置: 首页 > 综合 > 正文

你看糊涂了吗?解析C中复杂的声明

2017年12月15日 ⁄ 综合 ⁄ 共 1350字 ⁄ 字号 评论关闭

复杂的声明

考虑下面的一个声明:

char *(*(*a[])())();

使用由内到外的阅读方法,并遵循[]()的结合性强于*的规则,依然很难得到这个声明的准确描述和含义。我们使用另一种方法,“声明模仿使用”

*(*(*a[])())()  是一个     char

(*(*a[])())()   是一个    指向char

*(*a[])()       是一个    返回指向char的函数

(*a[])()        是一个    指向返回指向char的函数的指针

*a[]            是一个    返回指向返回指向char的函数的指针的函数

a[]             是一个    指向返回指向返回指向char的函数的指针的函数的指针

a               是一个    指向返回指向返回指向char的函数的指针的函数的指针数组

这种复杂的声明用得很少,当我们确实需要使用复杂声明的时候,我们一般不会直接使用一个晦涩难懂的声明语句,而是多次使用typedef来简化处理

比如:需要声明一个“指向返回指向返回指向char的函数的指针的函数的指针数组a”,初看起来实在是太复杂了,我们可以从里到外逐层进行类型定义

指向char                                                               typedef
char *pc;

返回指向char的函数                                                 typedef
pc fpc();

指向返回指向char的函数的指针                                         typedef
fpc *pfpc;

返回指向返回指向char的函数的指针的函数                            typedef
pfpcfpfpc();

指向返回指向返回指向char的函数的指针的函数的指针            typedef
fpfpc*pfpfpc;

指向返回指向返回指向char的函数的指针的函数的指针数组            pfpfpc
a[];





    考虑下面一个奇怪的语句:

    (*(void(*)())0)();

    这其中包含了类似函数声明的语句和强制类型转换的表达式。

    创意 首先要明白C语言关于声明的一条基本规则:按照使用的方式来声明。(另一种说法是:让声明符模仿标识符的最终用法。)

    比如:int *g(), (*h)();

    *g()就是一个int型数,而(*h)()返回的值也是一个int型值。

    创意 一旦我们知道了声明的基本原则,那么强制类型转换也变得容易了:就是把声明语句的分号和变量名称去掉,再用括号把修改后的表达式括起来就OK了。

    比如声明:int (*h) ();  声明了一个返回值为int型的函数指针,如果要将某个变量a强制转换为这种类型的指针,就可以使用
    (int (*) ())a;

    项目 A 弄清楚这两点,上面的这个语句就好理解了:

    首先,(void(*)())0 是将0强制转换为一种函数指针,这种函数返回void类型;

    接着,(*(void(*)())0)();解引用这个强制转换后的函数指针,将空参数传递给它,使其执行。

抱歉!评论已关闭.