形参
未出现函数调用时,函数中指定的形参并不占内存中的存储单元。只有在发生函数调用时,函数中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
实参与形参
在C语言中,实参向对形参的数据传递是“值传递”,单向传递,只由实参传给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。
在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。
从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。
局部变量
在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的。这称为“局部变量”。
外部变量
在函数内定义的变量是局部变量,而在函数之外定义的变量称为外部变量,外部变量是全局变量(也称全局变量)。全局变量可以为本文件中其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束。 全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元
从变量值存在的时间(即生存期)角度来分,又可以分为静态存储方式和动态存储方式。
静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式。
动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式。
存储空间可以分为三部分:
程序区
静态存储区
动态存储区
存储类别指的是数据在内存中存储的方式。按照存储方式可以分为两大类:静态存储类和动态存储类。具体包含四种:
自动的(auto)
静态的(static)
寄存器的(register)
外部的(extern)
根据变量的存储类别,可以知道变量的作用域和生存期。
自动变量
函数中的局部变量,如不专门声明为static存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。
静态局部变量
有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量已有值,就是上一次函数调用结束时的值。这时就应该指定该局部变量为“静态局部变量”,用关键字static进行声明。
静态局部变量与自动变量的区别
(1) 静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储区空间而不占静态存储区空间,函数调用结束后即释放。
(2) 对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而对自动变量赋初值,不是在编译时进行的,而是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
(3)如在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配的单元中的值是不确定的。
(4) 虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。
寄存器变量,用关键字register作声明
C语言允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。由于对寄存器的存取速度远高于对内存的存取速度,因此这样做可以提高执行效率。
外部变量
外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。
(1)从作用域角度分,有局部变量和全局变量。它们采用的存储类别如下:
局部变量 |自动变量,即动态局部变量
(离开函数,值就消失)
|静态局部变量(离开函数,值仍保留)
|寄存器变量(离开函数,值就消失)
|(形式参数可以定义为自动变量或寄存
器变量)
全局变量 |静态外部变量(只限本文件引用)
|外部变量
(即非静态的外部变量,允许其他文件引用)
(2)从变量存在的时间(生存期)来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。
动态存储 |自动变量(本函数内有效)
|寄存器变量(本函数内有效)
|形式参数(本函数内有效)
静态存储 |静态局部变量(函数内有效)
|静态外部变量(本文件内有效)
|外部变量(其他文件可引用)
((3)从变量值存放的位置来区分,可分为:
内存中静态存储区 |静态局部变量
|静态外部变量(函数外部静态变量)
|外部变量(可为其他文件引用)
内存中动态存储区:自动变量和形式参数
CPU中的寄存器:寄存器变量
(4) 关于作用域和生存期的概念。从前面叙述可以知道,对一个变量的性质可以从两个方面分析,一是变量的作用域,一是变量值存在时间的长短,即生存期。前者是从空间的角度,后者是从时间的角度。二者有联系但不是同一回事。
(5)static对局部变量和全局变量的作用不同。对局部变量来说,它使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化(局部于本文件),但仍为静态存储方式。从作用域角度看,凡有static声明的,其作用域都是局限的,或者是局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)
函数
函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数不能被其他文件调用。根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数。
内部函数
如果一个函数只能被本文件中其他函数所调用,它称为内部函数。在定义内部函数时,在函数名和函数类型的前面加static。即
static 类型标识符 函数名(形参表)
如 static int fun ( int a , int b )
外部函数
在定义函数时,如果在函数首部的最左端加关键字extern,则表示此函数是外部函数,可供其他文件调用。如果在定义函数时省略extern,则隐含为外部函数。在需要调用此函数的文件中,用extern对函数作声明,表示该函数是在其他文件中定义的外部函数。