简析令人头大的定义 void ((f[])())()

解析

在v2ex闲逛发现有人在谈怎么学习c语言,有人推荐tcpl,然后写了个反人类的变量定义 void (*(*f[])())(),这么复杂的定义在c++实际的项目中其实也不常见,反正我喜欢研究下到底是什么,就花了点时间去看看这个定义,其实复杂的变量定义在csdn有一个人详细的解读过,不过凭着三脚猫的功底,我还是按着自己的理解去解读下吧。

首先提取下变量名,这个就是我们实际定义的变量f,我们定义了变量f,但是类型还未知,反正知道是

void (*(*[])())()

类型的定义。

然后呢,我们看到了左侧的*和右侧的[],我们知道在没有()的情况下,类型是倾向于和右侧的[]结合的,那么我们知道f是一个数组(当然可以把它弱化为对数组的指针,一样的)。

为了简化理解,我们修改一下这个变量的定义。

void (*(*f[1])())()

这样我们就很简单的知道,f是一个数组,有1个元素,剩下未知的就是数组元素的类型了。

我们来提取下数组的元素类型:

void (*(*)())()

的确是反人类的类型,我们依旧按步骤走。我们朝着刚把变量名移走的位置看,看到了*(*)()的类型声明,那么究竟这个类型是什么呢?啥都不像!可是最像什么呢?对,有这个类型的,也只有函数指针了。

我们按着函数指针的方向走,发现右边的()不就是代表有没参数么!对,这条路肯定走的通,剩下的就是解析函数的返回值类型了,于是我们继续把返回值的类型提取出来:

void(*)()

这样就很清楚了吧,函数的返回值也是一个函数指针,参数空返回值也为空,这样我们就把这个变量的类型给解出来了。

按白话说,这个变量其实是一个数组(指针),里面的每一个元素(指向的元素)都是一个函数指针,所以这个数组的大小其实是可以知道的。然后这个函数指针,参数为空,返回值也是一个函数指针,返回值的函数指针则是一个参数为空,返回值为空的函数指针。

下面写一个简单的函数来验证下上述的想法。

typedef void(*ReturnFunc)();

void retfn()
{
    MessageBox(NULL, "call", "t", MB_OK);
}

ReturnFunc callfn()
{
    return retfn;
}

void param(void (*(*f2[])())())
{
    f2[0]()();
}

int main() {
    void (*(*f1[1])())();
    f1[0] = &callfn;
    f1[0]()();

    void (*(*f2[])())() = f1;
    f2[0]()();

    param(f1);

    return 0;
}
共 0 条回复
暂时没有人回复哦,赶紧抢沙发
发表新回复

作者

sryan
today is a good day