声明那回事儿

本文转自:http://edsionte.com/techblog/archives/2350

C语言中的变量声明是让程序员比较苦恼的一件事,因为过多的优先级规则使得阅读声明并不能像自然方式那样从左至右的阅读。比如下面这个声明:
int (*(*fun)())();
对于这个声明,你能准确说出它的含义吗?这个声明涉及到本文的两大主题:什么是声明和声明的阅读规则。本文的最后将给出这个声明的准确含义。

声明和定义在C语言中,提到声明就不得不提到定义。这里说的声明既包含变量的声明又包含函数的声明。对于函数的定义和声明易于理解,比如:

int myfun2(); 
int myfun2() 
{ 
printf("I am myfun2~\n"); 
return 0; 
} 

所谓函数的定义就是对该函数进行具体的功能实现,而函数声明则是对该函数返回值和参数类型的说明,使得其他函数感知到这个函数的存在,以便在需要时直接调用该函数。
变量的声明具体分为两种情况:定义型声明和外部引用型声明。
定义型声明其实就等价于定义。C语言的定义是指为变量分配内存空间,并在需要时为其赋一个初值。定义型声明用于创建一个新的变量,它在定义这个变量的同时也声明了这个变量。比如下述代码就声明(定义)了一个变量num,并将0作为其初值。

int num = 0;

使用外部引用型声明是由于要在当前程序中使用定义在其他文件中的变量。也就是说这个变量是已存在的,因此这种声明并不包含变量的定义。比如:

file1: 
int a = 100; 
file2: 
extern int a; 

C语言中的变量只能有一个定义,但是它却可以有多个extern的声明。因为extern声明并不分配内存空间,只是告诉引用这个变量的函数:这个变量已经定义过了,你可以直接的使用。
声明的组成声明确定了变量的基本类型和相应的初值(如果需要的话)。一个完整的声明包括三部分:一个类型说明符,一个或多个声明器(declarator)和一个分号。
类型说明符用于描述所要声明变量的类型;分号说明了声明的结束;声明器是标示符以及和它组合在一起的指针符、函数括号和数组下标等,有时候也将初始化内容放在声明器中。多个声明器用逗号隔开。关于声明和声明器的关系可参考下图:


该图所示的语句声明了四个变量,其基本类型都是整型。由于四个变量分别对应着不同的声明器,则最终的变量类型就有所不同。整型变量a的声明器即为标示符a;第二个声明器为b=NULL,它声明b是一个指针变量,其初值为NULL。由于类型说明符为int,则说明了b是一个指向整型的指针;第三个声明器为(c)[20],它声明c是一个数组指针,该指针指向拥有20个元素的数组。由类型说明符得知该数组的元素都是整型的;最后一个声明器为j[20],其说明j是一个指针数组,该数组有20个元素,每个元素都是指向整型变量的指针。
优先级规则了解了声明的组成后,到了该给出声明优先级规则的时候了。C语言中声明的优先级规则如下:
1.声明从最左的标示符开始,然后按照下面的优先级规则依次读取;
2.具体的优先级为:
[list]
[
]2.1 被括号括起来的那部分;
[]2.2 后缀部分;如果后缀为( ),表明这是一个函数;如果后缀为[ ],表明这是一个数组;
[
]2.3 前缀部分;*表示指向…的指针;
[/list]3.如果const或volatile关键字后紧邻基本类型说明符,则它作用于该类型的变量;否则,const和volatile作用于仅靠它左边的星号,即作用于指针变量;
上述规则需要参考实际的声明来慢慢理解。下面通过两个简单的声明举例来说明上述优先级规则:

/* 
* Author: edsionte 
* Email: edsionte@gmail.com 
* Time: 2011/02/01 
*/ 
#include 
int (*myfun1())(); 
int myfun2(); 
int (*myfun1())() 
{ 
//myfun1 return a pointer which point a function; 
//The return function hasn't argument and reurun a int value; 
int (*fun2)(); 
printf("I am myfun1~\n"); 
fun2 = myfun2; 
return fun2; 
} 
int myfun2() 
{ 
printf("I am myfun2~\n"); 
return 0; 
} 
int main() 
{ 
int (*(*fun1)())(); 
int (*fun2)(); 
 fun1 = myfun1; 
fun2 = fun1(); 
fun2(); 
return 0; 

参考:
《C专家编程》 人民邮电出版社;(美)林登(LinDen.P.V.D) 著,徐波 译;

:dizzy::dizzy::dizzy: