[译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)
在C/C++中,指针的类型分析有时是异常复杂的,昨日偶得一篇佳文,特译之与大家共享!
正文:
顺时针规则
by David Anderson
现在,有一种称之为“顺时针规则”的方法能让C程序员分析任何让人头疼的C语句声明。
简言之,此法有如下3步:
- 从一个未知的元素开始,按顺时针方向移动,当遇到一个元素时,用对应的英语句子代替之:
[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页的例子练习这个规则!
注:
- 因为个人水平,译文有所粗糙,敬请谅解!
- 原文链接