[C专家]分析C语言声明——声明是如何形成的[1]
2017-08-12 19:38
399 查看
让我们先来看一些C语言的术语以及一些能组合成一个声明的单独语法成分。其中一个非常重要的成分就是声明器(declarator)——它是所有声明的核心。简单地说,声明器就是标识符以及与它组合在一起的任何指针、函数括号、数组下标等,如下表所示。为了方便起见,我们把初始化内容(initializer)也放到里面,并分类表示。
声明器
注:上表中* const volatile、* volatile、* const、* volatile const,这里的const和volatile是用于限定指针的。
一个声明由下表所示的各个部分组成(并非所有的组合形式都是合法的,但这个表描述了我们进一步讨论所要用到的词汇)。声明确定了变量的基本类型以及初始化值(如果有的话)。
声明说明符
注:这里的类型限定符const和volatile是用于限定类型说明符指定的类型,与上面* const volatie等是不一样的。
注:上表中倒数第二行“零个或多个声明器”的意思是,举例来说就是一次声明多个:static const int i,j,k,l,m.n;,这里的j、k、l、m、n就属于倒数第二行中提到的。而这里的i就是倒数第三行中提到的。
注:const static int * const p();
const、static、int 属于声明说明符;* const、p()属于声明器
p是一个函数,它返回一个指针,这个指针是只读的,这个指针指向一个int类型的对象,并且该对象也是只读的,最后这个函数只能在声明所在的文件内可见。
声明说明符:声明说明符是以嵌套形式组织的,以上为例有三个声明说明符const、static、int。
const是一个类型说明符,它后面的声明说明符是static int;
static是一个存储说明符,它后面的声明说明符是int;
int是一个类型说明符,它后就就是声明器,已经没有嵌套了
对于声明说明符的排列顺序,C标准并没有规定,谁嵌套谁都可以,所以static const int、int static const 、int const static 都是一个意思。
让我们看一下如果你使用这些部件来构造一个声明,情况能够复杂到什么程度。同时要记住,在合法的声明中存在限制条件。你不可以像下面那样做:
函数的返回值不能是一个函数,所以像foo()()这样是非法的
函数的返回值不能是一个数组,所以像foo()[]这样是非法的
数组里面不能有函数,所以像foo[]()这样是非法的
但像下面这样则是合法的:
函数的返回值允许是一个函数指针,如: int (*fun())()
函数的返回值允许是一个指向数组的指针,如:int (* foo())[]
数组里面允许有函数指针,如:int (* foo[])()
数组里面允许有其它数组,如:int foo[][]
扩展
C标准中的“右左法则”是用来辨识一个声明的方法,其具体流程如下:
首先从未定义的标识符开始,然后往右看,再往左看。每当遇到圆括号时,就应该调转阅读方向。一旦解析完圆括号里面所有东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
例1:int (*func)(int *p);
首先找到未定义标识符func,它的外面有一对圆括号,而且它的左边有一个*,所以func是一个指针;
跳出这个圆括号,看右边,也是一个圆括号,说明(*func)是一个函数,而func是一个指向函数的指针,这类函数有一个int *类型的形参;
跳出这个圆括号,看左边,是一个int,说明这类函数返回的是一个int类型的值
例2:int (*func)(int *p, int (*f)(int *));
未定义标识符func,它外面有一对圆括号,而且它的左边有一个*,所以func是一个指针;
跳出这个圆括号,看右边,也是一个圆括号,说明(*func)是一个函数,而func是一个指向函数的指针,这类函数具有int * 和 int (*)(int *)这样的形参;
跳出这个圆括号,看左边,是一个Int,说明这类函数返回的是一个int类型的值。
例3:int (*func[5])(int *p);
未定义标识符func,看右边,有一对方括号,说明它是一个具有5个元素的数组;
看左边,是一个*,说明数组的元素是指针;
跳出这个圆括号,看右边,也是一对圆括号,说明数组中的元素是函数指针,这类函数具有int *这样的形参;
跳出这个圆括号,看左边,是一个int,说明这类函数返回的是一个int类型的值
例4:int (*(*func)[5])(int *p);
未定义标识符func,看左边,是一个*,说明它是一个指针;
跳出这个圆括号,看右边,是一对方括号,说明(*func)是一个数组,一个指向数组的指针;
看左边,是一个*,数组的元素是指针;
跳出这个括号,看右边,是一对圆括号,说明数组中的元素时函数指针,这类函数具有int * 这样的形参;
跳出这个括号,看左边,是一个int,说明这类函数返回的是一个Int类型的值
例5:int (*(*func)(int *p))[5];
未定义标识符func,看左边,是一个*,说明它是一个指针;
跳出这个圆括号,看右边,是一对圆括号,说明func是一个指向函数的指针,这类函数具有int* 这样的参数;
看左边,是一个*,说明这类函数返回的是一个指针;
跳出这个圆括号,看右边,是一对方括号,说明这个返回的指针指向一个具有5个元素的数组;
看左边,是一个int,说明数组的元素是Int类型
[非法] 例6:int func(void)[5]
未定义标识符func,看右边,是一对括号,func是一个函数,没有参数;
由于右边是一对方括号,所以函数返回的是一个具有5个元素的数组;
这个数组的元素是int类型
声明器
注:上表中* const volatile、* volatile、* const、* volatile const,这里的const和volatile是用于限定指针的。
一个声明由下表所示的各个部分组成(并非所有的组合形式都是合法的,但这个表描述了我们进一步讨论所要用到的词汇)。声明确定了变量的基本类型以及初始化值(如果有的话)。
声明说明符
注:这里的类型限定符const和volatile是用于限定类型说明符指定的类型,与上面* const volatie等是不一样的。
注:上表中倒数第二行“零个或多个声明器”的意思是,举例来说就是一次声明多个:static const int i,j,k,l,m.n;,这里的j、k、l、m、n就属于倒数第二行中提到的。而这里的i就是倒数第三行中提到的。
注:const static int * const p();
const、static、int 属于声明说明符;* const、p()属于声明器
p是一个函数,它返回一个指针,这个指针是只读的,这个指针指向一个int类型的对象,并且该对象也是只读的,最后这个函数只能在声明所在的文件内可见。
声明说明符:声明说明符是以嵌套形式组织的,以上为例有三个声明说明符const、static、int。
const是一个类型说明符,它后面的声明说明符是static int;
static是一个存储说明符,它后面的声明说明符是int;
int是一个类型说明符,它后就就是声明器,已经没有嵌套了
对于声明说明符的排列顺序,C标准并没有规定,谁嵌套谁都可以,所以static const int、int static const 、int const static 都是一个意思。
让我们看一下如果你使用这些部件来构造一个声明,情况能够复杂到什么程度。同时要记住,在合法的声明中存在限制条件。你不可以像下面那样做:
函数的返回值不能是一个函数,所以像foo()()这样是非法的
函数的返回值不能是一个数组,所以像foo()[]这样是非法的
数组里面不能有函数,所以像foo[]()这样是非法的
但像下面这样则是合法的:
函数的返回值允许是一个函数指针,如: int (*fun())()
函数的返回值允许是一个指向数组的指针,如:int (* foo())[]
数组里面允许有函数指针,如:int (* foo[])()
数组里面允许有其它数组,如:int foo[][]
扩展
C标准中的“右左法则”是用来辨识一个声明的方法,其具体流程如下:
首先从未定义的标识符开始,然后往右看,再往左看。每当遇到圆括号时,就应该调转阅读方向。一旦解析完圆括号里面所有东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
例1:int (*func)(int *p);
首先找到未定义标识符func,它的外面有一对圆括号,而且它的左边有一个*,所以func是一个指针;
跳出这个圆括号,看右边,也是一个圆括号,说明(*func)是一个函数,而func是一个指向函数的指针,这类函数有一个int *类型的形参;
跳出这个圆括号,看左边,是一个int,说明这类函数返回的是一个int类型的值
例2:int (*func)(int *p, int (*f)(int *));
未定义标识符func,它外面有一对圆括号,而且它的左边有一个*,所以func是一个指针;
跳出这个圆括号,看右边,也是一个圆括号,说明(*func)是一个函数,而func是一个指向函数的指针,这类函数具有int * 和 int (*)(int *)这样的形参;
跳出这个圆括号,看左边,是一个Int,说明这类函数返回的是一个int类型的值。
例3:int (*func[5])(int *p);
未定义标识符func,看右边,有一对方括号,说明它是一个具有5个元素的数组;
看左边,是一个*,说明数组的元素是指针;
跳出这个圆括号,看右边,也是一对圆括号,说明数组中的元素是函数指针,这类函数具有int *这样的形参;
跳出这个圆括号,看左边,是一个int,说明这类函数返回的是一个int类型的值
例4:int (*(*func)[5])(int *p);
未定义标识符func,看左边,是一个*,说明它是一个指针;
跳出这个圆括号,看右边,是一对方括号,说明(*func)是一个数组,一个指向数组的指针;
看左边,是一个*,数组的元素是指针;
跳出这个括号,看右边,是一对圆括号,说明数组中的元素时函数指针,这类函数具有int * 这样的形参;
跳出这个括号,看左边,是一个int,说明这类函数返回的是一个Int类型的值
例5:int (*(*func)(int *p))[5];
未定义标识符func,看左边,是一个*,说明它是一个指针;
跳出这个圆括号,看右边,是一对圆括号,说明func是一个指向函数的指针,这类函数具有int* 这样的参数;
看左边,是一个*,说明这类函数返回的是一个指针;
跳出这个圆括号,看右边,是一对方括号,说明这个返回的指针指向一个具有5个元素的数组;
看左边,是一个int,说明数组的元素是Int类型
[非法] 例6:int func(void)[5]
未定义标识符func,看右边,是一对括号,func是一个函数,没有参数;
由于右边是一对方括号,所以函数返回的是一个具有5个元素的数组;
这个数组的元素是int类型
相关文章推荐
- 如何分析复杂的C语言声明
- C专家编程学习之第三章——分析C语言的声明
- C专家编程——分析C语言的声明
- c专家编程笔记之第三章分析c语言的声明
- C专家编程-Chapter3 C语言声明分析2
- 如何分析复杂的C语言声明
- [C专家]分析C语言声明——关于枚举
- C专家编程-分析C语言的声明
- [C专家]分析C语言声明—— 关于结构体
- [C专家]分析C语言声明——只有编译器才会喜欢的语法
- 【C专家编程】第3章 分析C语言的声明
- [C专家]分析C语言声明——关于联合
- 【c专家编程】分析c语言的声明
- 读《C专家编程》笔记-第三章 分析C语言的声明
- 声明是如何形成的
- 程序比程序员更理解c语言! cdecl程序(分析c语言的声明
- c语言声明的分析方法
- C语言的声明分析
- 如何优雅的解析C语言声明系统
- 《C专家编程》第三章——分析C语言的声明