当没有标识符时,如何读取复杂的C++类型声明?

问题描述 投票:2回答:1

在读取复杂的C++类型时,有众所周知的螺旋和左右规则等,如

int (*(*foo)(char *,double))[9][20];

Foo是一个指针(改变方向,移出括号)

的函数,并返回(再次改变方向)。

指针指向

一个尺寸为9,20的二维数组(到达右端,外侧螺旋向左)。

整数。

但是,如果没有标识符,比如在定义函数参数的类型时,我如何处理这样的类型呢?

void foo(int *(*(* )(int(* )(int (* )(int))))())
                  ^       ^        ^
                  identifiers omitted

我如何以一种直观的方式识别最内部的元素? 顺便说一下,即使是cdecl工具在最后这个例子中也给出了一个语法错误,但它确实可以编译。

当然,编译器有一个定义良好的方法来解析这样的胡言乱语。它怎么知道从哪里开始呢?

c++ types syntax
1个回答
3
投票

读取复杂类型的规则假设类型已经被解析过了(而且你知道 "最里面 "的点在哪里)。解析的规则是从外到内,和数学课上读复杂表达式一样。当你打到小括号的时候,给它起个名字,然后再来找它(除非它很简单,可以自己处理)。声明:我使用文本编辑器来定位匹配的小括号。 ;)

这个声明的另一个考虑是,一旦一个类型是一个函数,参数列表中的乱七八糟的东西就是一个单独的解析。例如,当解析 void (*)(big old mess),你有一个指向函数的指针。这一大堆乱七八糟的东西对于函数的签名来说是需要的,但对于理解你正在处理一个函数来说却不需要。

继续说说眼前的例子。

void foo(int *(*(* )(int(* )(int (* )(int))))())

在读完 voidfoo,你打了括号,里面有一个复杂的混乱。给这个乱七八糟的东西起个名字。

void foo( A )

哪儿 Aint *(*(* )(int(* )(int (* )(int))))(). 所以你最外层的解析是一个单调函数,返回的是 void,我们仍然需要解析参数。A. 请注意,我们已经知道这段文字的总体目的是什么:它声明了一个名为 foo. 其余类型没有名称,因为参数的名称是可选的。

A: int *( B )()

其中 B*(* )(int(* )(int (* )(int))). 所以,参数要 foo 是一个最外层类型为空函数的东西,它返回一个指向 int. 我们大概会发现 "something "是一个指针,但我们仍然需要解析一下 B 来证实这一点。(好了,往前跳一下,看到的是 B 以星号开头。这是一个指向这个空函数的指针)。)

B: *(* )( C )

其中 Cint(* )(int (* )(int)). 这是一个指向单调函数的指针,它的参数是一些复杂类型,它的返回值是指向我们之前解析的东西(空值函数)的指针。与初始解析一样,我们发现了另一个开始读取的地方,因为乱七八糟的东西已经被推到了参数列表中。这个参数是 foo 是一个指向单数函数的指针,该函数的参数是一些复杂类型,其返回值是一个指向空函数的指针,该函数返回一个指向 int.

C: int(* )( D )

哪儿 Dint (* )(int). 同样,乱七八糟的东西已经移到了参数列表中。这个层次的东西是一个指向单调函数的指针,它返回一个 int.

D: int (* )(int)

最后,简单地说:一个指向单调函数的指针,它取一个 int 并返回一个 int.

所以...

此声明 foo 是一个单调函数,返回 void 的指针,返回一个空值函数的指针,返回一个向 int,其参数是一个指向单调函数的指针,返回的是 int 其参数是一个指向单调函数的指针,返回的是 int 其参数为 int.

英文版本和代码一样容易理解,不是吗?:) 让我们试试更有条理的东西。

  • foo
    • 返回。 void
    • 参数: 指向一个函数的指针
      • 返回 指向一个函数的指针
        • 返回 指向 int
      • 参数: 指向函数的指针
        • 返回。 int
        • 返回: 参数。 指向函数的指针
          • 返回。 int
          • Parameter: int

Whew. 不要在家里这样做,孩子们。给你的中间类型起个名字,省得程序员费心。

© www.soinside.com 2019 - 2024. All rights reserved.