首先,declaration分为两种:external declaration(在函数外的声明) 和internal declaration(在函数内的声明)。由于不能在函数内定义函数,因此函数定义总是external declaration。
接下来明确storage class specifier,有4种storage class specifier:auto, extern, register, static。其中只有register可以用在function prototype和function definition中。并且不能对声明为register的变量进行取地址(&)操作,因为一些处理器不支持可寻址寄存器。只有extern 和static 可以用于函数。
如果定义变量或函数时未指定storage class specifier,则采用默认值。这个默认值对于函数来说是extern。对于变量来讲则取决于declaration的类型。如果变量是external declaration,则默认值是extern,如果是internal declaration,则默认为auto。
关于Duration。
有3种类型的duration:static duration, automatic duration, allocated duration。
allocated duration是指用malloc ()等函数动态分配的存储,其lifetime是从allocation到deallocation。
在函数内声明且没有用static和extern关键字限定的变量具有automatic duration。其lifetime在相应的block内。
函数和用extern、static限定的变量具有static duration。其lifetime是程序整个执行周期。它们只在程序执行前被初始化一次。
一个object的duration取决于它的storage class specifier。
下面的表格作了一个总结,其中的linkage在下面讨论:
Storage Class Specifier | Function or Data Object | Linkage | Duration |
static | either | internal | static |
extern | either | probably external | static |
none | function | probably external | static |
none | data object | external | static |
Storage Class Specifier | Function or Data Object | Linkage | Duration |
register | data object only | none | automatic |
auto | data object only | none | automatic |
static | data object only | none | static |
extern | either | probably external | static |
none | data object | none | automatic |
none | function | probably external | static |
Table 2. Internal declarations
关于Scope。
共有4种scope:function scope, file scope, block scope, function prototype scope。
只有label(used in goto statement)具有function scope。在当前函数内可用,而与函数内的block structure无关。label不是object,不占存储,也没有duration 和linkage的概念。
任何在函数外声明的变量具有file scope,在当前整个source file内可用。
函数定义中的formal parameter以及在compound statement内定义的变量具有block scope,在其相应的"}"之前可用。
在函数原型声明中的变量具有function prototype scope,只在当前函数原型声明语句中可用。
关于Linkage。
C99标准把一个object的Accessibility称为linkage,有3种linkage:external linkage,internal linkage,no linkage。
具有external linkage的对象可在整个program范围(跨越多个source file)内被访问。函数默认具有external linkage,任何在函数外声明的变量也具有external linkage。但是,可以用static关键字使它们成为internal linkage。也就是只能在当前source file内被访问,而不能跨越多个source file。在函数内声明的变量具有no linkage。
linkage定义了在不同scope中引用同一object的规则。比如具有external linkage的变量,在整个program的所有source file中与之相同的变量名都引用同一个object。
下面的例子可以在一定程度上说明external linkage与internal linkage:
file1.c
/* first file */ #include <stdio.h> int i; int main () { void f_in_file2 (); i = 0; f_in_file2 (); printf ("i = %d/n", i); return 0; }
file2.c
/* second file */ extern int i; void f_in_file2 () { i++; }
那么上面的程序编译将会报错。因为此时变量i与函数f_in_file2 ()都是internal linkage,只限于当前source file可访问。
References:
1 C99标准
2 The C Book, http://publications.gbdirect.co.uk/c_book/