[译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)

时间:2021-04-04 20:08:17

在C/C++中,指针的类型分析有时是异常复杂的,昨日偶得一篇佳文,特译之与大家共享!

正文:

顺时针规则  

                                                                                                                                               by David Anderson

现在,有一种称之为“顺时针规则”的方法能让C程序员分析任何让人头疼的C语句声明。

简言之,此法有如下3步:

  1. 从一个未知的元素开始,按顺时针方向移动,当遇到一个元素时,用对应的英语句子代替之:

  [X] or []

     => Array X size of... or Array undefined size of...

  (type1, type2)

    => function passing type1 and type2 returning...

  *

    => pointer(s) to...

  2. 按顺时针方向保持移动直到所有的符号被覆盖为止;

  3. 总是先在括号里面解决任何元素(注:原文用的是resovle anything,我也不知如何翻译更为恰当)

 

例子#1. 简单的声明

+-------+
                     | +-+   |
                     | ^ |   |
                char *str[10];
                 ^   ^   |   |
                 |   +---+   |
                 +-----------+
我们要问的问题是:str是什么东东?
  ``str is an...
  • 我们从 str 开始按顺时针方向移动,我们遇到的第一个字符是 [ ,这意味着有一个数组,所以……

      ``str is an array 10 of...

  • 继续按顺时针方向移动,下个遇到的东东是`*`,这意味着有一个指针,所以……

      ``str is an array 10 of pointers to...

  • 继续按顺时针方向移动直到了这一行的末尾(即`;`),继续移动直到我们看到`char`类型,所以……

      ``str is an array 10 of pointers to char''

  • 现在,我们已经“访问”了所有的符合,因此我们的分析也就完成了。

 

例子#2。函数指针的声明

               +--------------------+
                     | +---+              |
                     | |+-+|              |
                     | |^ ||              |
                char *(*fp)( int, float *);
                 ^   ^ ^  ||              |
                 |   | +--+|              |
                 |   +-----+              |
                 +------------------------+
我们要问的问题是:fp是什么东东?
  ``fp is a...
  • 按顺时针方向移动,我们遇到的第一个字符是`)`,因此我们在括号内部按顺时针方向移动,然后遇到的下一个符合是`*`,所以……

      ``fp is a pointer to...

  • 我们现在已经在括号外部,继续按顺时针方向移动,我们遇到了`(`,所以有一个函数,因此……

      ``fp is a pointer to a function passing an int and a pointer to float returning...

  • 继续按其移动,下个字符是`*`,即是指针,所以……

      ``fp is a pointer to a function passing an int and a pointer to float returning a pointer to...

  • 继续按其移动,下个字符是`;`,但是我们还没有“访问”完所有的符号,所以继续按顺时针方向移动直到我们遇到了类型`char`,所以……

      ``fp is a pointer to a function passing an int and a pointer to float returning a pointer to a char''

 

例子#3.终极版

                 +-----------------------------+
                      |                  +---+      |
                      |  +---+           |+-+|      |
                      |  ^   |           |^ ||      |
                void (*signal(int, void (*fp)(int)))(int);
                 ^    ^      |      ^    ^  ||      |
                 |    +------+      |    +--+|      |
                 |                  +--------+      |
                 +----------------------------------+
我们要问的问题是:signal是什么东东?
注意到signal是在括号里面,所以我们先从这里(即signal)开始!
  • 按顺时针方向移动,遇到的第一个字符是`(`,所以……

      ``signal is a function passing an int and a...

  • 嘿嘿,对于fp,我们可以使用同样的规则,所以……fp是什么东东?fp在括号里面,所以我们继续直到遇到字符`*`,所以……

      fp is a pointer to...

  • 继续移动,然后遇到`(`,所以……

      ``fp is a pointer to a function passing int returning...''

  • 然后我们离开函数的括号即可看到`void`,所以……

      ``fp is a pointer to a function passing int returning nothing (void)''

  • 我们已经完成了fp的分析,所以把它和signal的分析连接起来,有……

      ``signal is a function passing an int and a pointer to a function passing an int returning nothing (void) returning...

  • 我们仍然在括号里面,所以下个字符是`*`,即……

      ``signal is a function passing an int and a pointer to a function passing an int returning nothing (void) returning a pointer to...

  • 现在我们已经完成了这个括号里面的部分,所以继续移动,然后我们遇到了另外一个`(`,所以……

      ``signal is a function passing an int and a pointer to a function passing an int returning nothing (void) returning a pointer to a function passing an int returning...

  • 最后,继续移动直到遇到左边的关键字`void`,所以对signal最后的定义即为:

      ``signal is a function passing an int and a pointer to a function passing an int returning nothing (void) returning a pointer to a function passing an int returning nothing (void)''

 

同样的规则亦适用于 constan 和 volatile类型的声明,例如:    

    const char *chptr;
  • 现在,chptr是什么东东?

      ``chptr is a pointer to a char constant''

那下面这个:

    char * const chptr;
  • 现在,chptr是什么东东?

      ``chptr is a constant pointer to char''

最后,

    volatile char * const chptr;
  • 现在,chptr是什么东东?

      `chptr is a constant pointer to a char volatile.''

K&R II 第122页的例子练习这个规则!

 

注:

  1. 因为个人水平,译文有所粗糙,敬请谅解!
  2. 原文链接