关于变量的声明和定义
一个函数一般由两部分组成:声明部分和执行语句。声明部分的作用:是对有关的标识符(如变量、函数、结构体、共用体等)的属性进行声明。对于函数而言,声明和定义的区别是明显的,函数的声明是函数的原型,而函数的定义是对函数功能的定义。对被调用函数的声明是放在主调函数的声明部分中的,而函数的定义显然不在声明部分的范围内的,它是一个独立的模块
对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:
- 需要建立存储空间的,此为定义性声明,简称定义
- 不需要建立存储空间的,此为引用性声明
广义的说,声明包括定义,但并非所有的声明都是定义。例如 int a;
,既是声明,也是定义;而对extern a;
而言,是声明而不是定义。一般为了叙述方便,把建立存储空间的声明称定义,而把不需要建立存储空间的声明称为声明。显然这里指的声明是狭义的,即非定义性声明。
外部变量定义和外部变量声明的含义是不同的。外部变量的定义只能有一次,它的位置在所有函数之外。在同一文件中,可以有多次对同一外部变量的声明,它的位置可以在函数内(哪个函数要用就在哪个函数中声明),也可以在函数之外(在外部变量的定义点之前)。系统根据外部变量的定义(而不是根据外部变量的声明)分配存储单元。对外部变量的初始化只能在“定义”时进行,而不能在“声明”中进行。所谓“声明”,其作用是声明该变量是一个已在其他地方已定义的外部变量,仅仅是为了扩展改变量的作用范围而作的“声明”
在函数中出现对变量的声明(除了用 extern 声明的以外)都是定义。在函数中对其他函数的声明不是函数的定义
内部函数和外部函数
函数本质上是全局的,因为定义一个函数的目的就是要被另外的函数调用。如果不加声明的话,一个文件中的函数既可以被文件中的其他函数调用,也可以被其他文件中的函数调用。但是,也可以指定某些函数不能被其他文件调用。根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数
内部函数
如果一个函数只能被本文件中的其他函数所调用,它称为内部函数
在定义内部函数时,在函数名和函数类型的前面加static
,即:
static 类型名 函数名(形参表);
内部函数又称为静态函数,因为它是用 static
声明的。
使用内部函数,可以使函数的作用域只局限于所在文件。这样子,在不同的文件中即使有同名的内部函数,也互不干扰。这就使它对外界“屏蔽”了
通常,一个大程序往往分工由不同的人分别编写不同的文件模块,在各人编写自己的文件模块时,不必担心所用函数是否会与其他文件模块中的函数同名
通常把只能由本文件使用的函数和外部变量放在文件开头,前面都冠以 static 使之局部化,其他文件不能引用。这就提高了程序的可靠性。
外部函数
如果在定义函数时,在函数的首部的最左端加关键字 extern
,则此函数是外部函数,可供其他文件调用
extern 函数类型 函数名(形参列表)
C语言规定,如果在定义函数时省略 extern
,则默认为外部函数
在需要调用此函数的其他文件中,需要对此函数作声明(不要忘记,即使在本文件中调用一个函数,也要用函数原型进行声明)。在对此函数作声明时,要加关键字 extern
,表示该函数“是在其他文件中定义的外部函数”
使用 extern
声明就能够在本文件中调用在其他文件中定义的函数,或者说把该函数的作用域扩展到本文件中
extern
声明的形式就是在函数原型基础上加关键字 extern
由于函数本质上是外部的,在程序中经常要调用其他文件中的外部函数,为方便编程,C语言允许在声明函数时省写 extern
用函数原型能够把函数的作用域扩展到定义该函数的文件之外(不必使用 extern
)。只要在使用该函数的每一个文件中包含该函数的函数原型即可。函数原型通知编译系统:该函数在本文件中稍后定义,或在另一文件中定义。
利用函数原型扩展函数作用域最常见的例子是 #include
指令的应用。在#include
指令所指定的“头文件”中包含调用库函数所需的信息