0%

顺时针规则--C语言声明

The “Clockwise/Spiral Rule”
By David Anderson

每个C程序员在脑袋里解析任何C声明的时候都会用到一种技术——顺时针/螺旋规则!

该规则只有简单的3步:

  1. 从未知元素开始,沿顺时针/螺旋方向移动;当遇到如下元素的时候,用相应的自然语言陈述出来:

    • [X] 或者 [] => 大小为…的数组X 或 未知大小数组的…(Array X size of… or Array undefined size of…)
    • (type1, type2) => 传入type1和type2参数、返回…的函数(function passing type1 and type2 returning…)
    • * => 指向…的指针(pointer(s) to…)
  2. 一直沿着顺时针往下进行,直到覆盖了所有的元素。

  3. 括号内的永远优先!

其实对英文来说就是不断在后边加定语,但对汉语来说,就需要不断在前边加定语。

1.简单声明

                 +-------+
                 | +-+   |
                 | ^ |   |
            char *str[10];
             ^   ^   |   |
             |   +---+   |
             +-----------+

首先需要问的是:str是什么?

str 是个…(str is an…)

  • 我们从str开始顺时针移动,碰到的第一个元素是[,这意味着我们碰到了个数组,于是就有…

    str是个大小是10、…的数组(str is an array 10 of…)

  • 继续顺时针,下一个遇到的是*,这意味着我们碰到了个指针,就有…

    str是个大小是10、指向…指针的数组(str is an array 10 of pointers to…)

  • 继续,下一个是该行结尾;;继续,接下来是char,因此…

    str是个大小是10、指向字符的指针的数组(str is an array 10 of pointers to char)

2.指向函数的指针的声明

                 +--------------------+
                 | +---+              |
                 | |+-+|              |
                 | |^ ||              |
            char *(*fp)( int, float *);
             ^   ^ ^  ||              |
             |   | +--+|              |
             |   +-----+              |
             +------------------------+

还是一样,首先要问:fp是什么?

fp 是个…(fp is a…)

  • 顺时针移动,首先看到了),因此fp就在括号中了,我们在括号中顺时针移动,下一个看到的是*,因此…

    fp 是个指向…的指针(fp is a pointer to…)

  • 跳出括号,继续顺时针转动,看到了(,这表明遇到了一个函数,就有…

    fp 是个指向传入参数是int和指向float的指针、返回值是…的函数的指针(fp is a pointer to a function passing an int and a pointer to float returning…)

  • 继续顺时针,看到了*,说明…

    fp 是个指向传入参数是int和指向float的指针、返回值是指向…的指针的函数的指针(fp is a pointer to a funciton passing an int and a pointer to float returning a pointer to…)

  • 继续,遇到;;再继续,遇到了char,因此…

    fp 是个指向传入参数是int和指向float的指针、返回值是指向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是个传入参数为int和…,返回…的函数(signal is a function passing an int and a…)

  • 接着,我们可以对fp用相同的规则,fp是什么?fp在括号中,首先遇到的是*,于是…

    fp是个指向…的指针(fp is a pointer to…)

  • 继续会遇到(,就有…

    fp是个指向传入参数是int、返回…的函数的指针(fp is a pointer to a function passing int returning…)

  • 接着,看到了void

    fp 是个指向传入参数是int、返回值为空(void)的函数的指针(fp is a pointer to a function passing int returning nothing (void))

  • 现在结束了对fp的解析,接着看signal

    signal是个传入参数为int和指向传入参数为int、返回值为空的函数的指针,返回值为…的函数(signal is a function passing an int and a pointer to a function passing an int returning nothing(void) returning…)

  • 现在还在括号内,接着的元素是*

    signal是个传入参数为int和指向传入参数为int、返回值为空的函数的指针,返回值为指向…的指针的函数(signal is a function passing an int and a pointer to a funciton passing an int returning nothing(void) returning a pointer to…)

  • 再继续,碰到了(

    signal是个传入参数为int何指向传入参数为int、返回值为空的函数的指针,返回值为指向一个传入参数为int、返回值为…的函数的指针的指针的函数(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 and returning…)

  • 终于到最后了,我们只剩下void这一个元素了,最终signale的定义为…

    signal是个传入参数为int何指向传入参数为int、返回值为空的函数的指针,返回值为指向一个传入参数为int、返回值为空的函数的指针的指针的函数(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 and returning nothing(void))

constvolatile的例子

规则一样的

1
const char *chptr:

chptr是个指向一个char常量(constant)的指针(chptr is a pointer to a char constant)

1
char * const chptr;

chptr是个指向char的常量指针(chptr is a constant pointer to char)

1
volatile char * const chptr;

chptr是个指向一个char原子(volatile)的常量指针(chptr is a constant pointer to a char volatile)


C的复杂声明其实就不断加定语,但是这个定语在修饰的是哪个主语,需要按照顺时针/螺旋规则来解释。熟悉了就好。


原文: The ``Clockwise/Spiral Rule’’