规则是正确的。但是,使用它时应该非常小心。
我建议以更正式的方式将其应用于 C99+ 声明。
这里最重要的是识别所有声明的以下递归结构(const、volatile、static、extern、inline、struct、union、typedef为简单起见已从图片中删除,但可以轻松添加回来):
base-type [derived-part1: *'s] [object] [derived-part2: []'s or ()]
是的,就是这样,四个部分。
where
base-type is one of the following (I'm using a bit compressed notation):
void
[signed/unsigned] char
[signed/unsigned] short [int]
signed/unsigned [int]
[signed/unsigned] long [long] [int]
float
[long] double
etc
object is
an identifier
OR
([derived-part1: *'s] [object] [derived-part2: []'s or ()])
* is *, denotes a reference/pointer and can be repeated
[] in derived-part2 denotes bracketed array dimensions and can be repeated
() in derived-part2 denotes parenthesized function parameters delimited with ,'s
[] elsewhere denotes an optional part
() elsewhere denotes parentheses
一旦你解析了所有 4 个部分,
[object] 是 [derived-part2(包含/返回)] [derived-part2(指向)] base-type 1。
如果有递归,你会在递归堆栈的底部找到你的object(如果有的话),它将是最里面的一个,你将通过返回并收集并获得完整的声明在每个递归级别组合派生部分。
解析时,您可以将[object] 移动到[derived-part2] 之后(如果有)。这将为您提供一个线性化、易于理解的声明(参见上面的 1)。
因此,在
char* (**(*foo[3][5])(void))[7][9];
你得到:
-
base-type = char
- 1级:
derived-part1 = *, object = (**(*foo[3][5])(void)), derived-part2 = [7][9]
- 2级:
derived-part1 = **, object = (*foo[3][5]), derived-part2 = (void)
- 3级:
derived-part1 = *, object = foo, derived-part2 = [3][5]
从那里:
- 3级:
*[3][5]foo
- 2级:
**(void)*[3][5]foo
- 1级:
*[7][9]**(void)*[3][5]foo
- 最后,
char*[7][9]**(void)*[3][5]foo
现在,从右到左阅读:
foo 是一个由 3 个数组组成的数组,其中包含 5 个指向函数的指针(不带参数),返回一个指向由 9 个指向 char 的指针组成的 7 个数组的指针的指针。
您也可以在此过程中反转每个derived-part2 中的数组维度。
这是你的螺旋法则。
而且很容易看到螺旋。您从左侧潜入嵌套更深的[object],然后在右侧重新浮出水面,却发现上层还有另一对左右,依此类推。