有众所周知的螺旋和左右规则等,用于读取复杂的 C++ 类型,例如
int (*(*foo)(char *,double))[9][20];
Foo 是一个指针(改变方向,移出括号)
到一个函数,它接受一个指向 char 和一个 double 的指针,然后返回(再次改变方向)
指向(再次括号,改变方向)的指针
维度为 9,20 的 2d 阵列(到达右端,向左外螺旋)
整数。
但是如果没有标识符,我该如何处理这样的类型,例如在定义函数参数的类型时:
void foo(int *(*(* )(int(* )(int (* )(int))))())
^ ^ ^
identifiers omitted
如何以直观的方式识别最里面的元素?
顺便说一句,即使 cdecl 工具在最后一个示例中也会出现语法错误,但它确实可以编译。
当然,编译器有一种明确定义的方式来解析这样的乱码。它怎么知道从哪里开始?
最佳答案
读取复杂类型的规则假定该类型已经被解析(并且您知道“最里面”的点在哪里)。由外而内的解析规则,就像在数学课上阅读复杂的表达式一样。当你打括号时,给它一个名字然后回来(除非它足够简单,可以自己处理)。免责声明:我使用文本编辑器来定位匹配的括号。 ;)
与此声明有关的另一个考虑因素是,一旦类型是函数,参数列表中的困惑就是单独的解析。比如解析void (*)(big old mess)
的时候,你有一个指向函数的指针。函数的签名需要大的旧困惑,但不是为了理解你正在处理一个函数。
继续手头的例子:
void foo(int *(*(* )(int(* )(int (* )(int))))())
看完
void
和 foo
,你在括号里面打了一个复杂的烂摊子。给那个烂摊子起个名字。void foo( A )
在哪里
A
是 int *(*(* )(int(* )(int (* )(int))))()
.所以你最外层的解析是一个返回 void
的一元函数,我们还需要解析参数A
.请注意,我们已经知道本文的总体目的是什么:它声明了一个名为 foo
的函数。 .其余类型没有名称,因为参数的名称是可选的。A: int *( B )()
在哪里
B
是 *(* )(int(* )(int (* )(int)))
.所以参数为foo
是其最外层类型为返回指向 int
的指针的空函数。 .想必我们会发现“某物”是一个指针,但我们还是需要解析B
确认。 (好的,向前略过一点,看到 B
以星号开头。它是指向这个空函数的指针。)B: *(* )( C )
在哪里
C
是 int(* )(int (* )(int))
.这是一个指向一元函数的指针,它的参数是某种复杂类型,它的返回值是一个指向我们之前解析的指针(空函数)。与最初的解析一样,我们发现了另一个开始阅读的地方,因为困惑已被插入参数列表。 foo
的参数是一个指向一元函数的指针,它的参数是某种复杂类型,它的返回值是一个指向一个空函数的指针,它返回一个指向 int
的指针.C: int(* )( D )
在哪里
D
是 int (* )(int)
.再一次,困惑已经进入了参数列表。这个级别的东西是一个指向返回 int
的一元函数的指针。 .D: int (* )(int)
最后,简单性:指向接受
int
的一元函数的指针。并返回 int
.所以....
这声明
foo
成为返回 void
的一元函数其参数是指向一元函数的指针,返回指向空函数的指针,返回指向 int
的指针,其参数是指向返回 int
的一元函数的指针其参数是指向返回 int
的一元函数的指针其参数为int
.英文版的代码和代码一样容易理解,不是吗? :) 让我们尝试一些更有条理的东西。
foo
void
int
的指针int
int
int
唷。 children ,不要在家里这样做。给你的中间类型命名,让程序员免去一些痛苦。
关于c++ - 没有标识符时如何读取复杂的 C++ 类型声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62182309/