博文
C++ 入门 第四章 4.15 内部函数和外部函数(2008-09-13 19:04:00)
摘要:
函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数只能被本文件调用,而不能被其他文件调用。根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数。
4.15.1 内部函数
如果一个函数只能被本文件中其他函数所调用,它称为内部函数。在定义内部函数时,在函数名和函数类型的前面加static。函数首部的一般格式为
static 类型标识符 函数名(形参表)
如
static int fun(int a,int b)
内部函数又称静态(static)函数。使用内部函数,可以使函数只局限于所在文件。如果在不同的文件中有同名的内部函数,互不干扰。通常把只能由同一文件使用的函数和外部变量放在一个文件中,在它们前面都冠以static使之局部化,其他文件不能引用。
4.15.2 外部函数
(1) 在定义函数时,如果在函数首部的最左端冠以关键字extern,则表示此函数是外部函数,可供其他文件调用。
如函数首部可以写为
extern int fun (int a, int b)
这样,函数fun就可以为其他文件调用。如果在定义函数时省略extern,则默认为外部函数。本书前面所用的函数都是外部函数。
(2) 在需要调用此函数的文件中,用extern声明所用的函数是外部函数。
例4.15 输入两个整数,要求输出其中的大者。用外部函数实现。
file1.cpp(文件1)
#include <iostream>
using namespace std;
int main( )
{extern int max(int,int); //声明在本函数中将要调用在其他文件中定义的max函数
int a,b;
cin>>a>>b;
cout<<max(a,b)<<endl;
return 0;
}
file2.cpp(文件2)
int max(int x,int y)
{int z;
z=x>y?x:y;
......
C++ 入门 第四章 4.13 变量属性小结[续](2008-09-13 19:03:00)
摘要:
如果一个变量在某个文件或函数范围内是有效的,则称该文件或函数为该变量的作用域,在此作用域内可以引用该变量,所以又称变量在此作用域内“可见”,这种性质又称为变量的可见性,例如图4.16中变量a、b在函数f1中可见。
如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的存储期,或称该变量在此时刻“存在”。书中表4.2表示各种类型变量的作用域和存在性的情况。
可以看到自动变量和寄存器变量在函数内的可见性和存在性是一致的。在函数外的可见性和存在性也是一致的。静态局部变量在函数外的可见性和存在性不一致。静态外部变量和外部变量的可见性和存在性是一致的。
(5) static声明使变量采用静态存储方式,但它对局部变量和全局变量所起的作用不同。对局部变量来说,static使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化(局部于本文件),但仍为静态存储方式。从作用域角度看,凡有static声明的,其作用域都是局限的,或者局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)。
4.14 关于变量的声明和定义
由第2章已经知道,一个函数一般由两部分组成: (1)声明部分; (2)执行语句。声明部分的作用是对有关的标识符(如变量、函数、结构体、共用体等)的属性进行说明。对于函数,声明和定义的区别是明显的,在本章4.4.3节中已说明,函数的声明是函数的原型,而函数的定义是函数功能的确立。对函数的声明是可以放在声明部分中的,而函数的定义显然不在函数的声明部分范围内,它是一个文件中的独立模块。
对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要建立存储空间的(如int a; );另一种是不需要建立存储空间的(如extern int a;)。前者称为定义性声明(defining declaration),或简称为定义(definition)。后者称为引用性声明(referenceing declaration)。广义地说,声明包括定义,但并非所有的声明都是定义。对“int a;” 而言,它是定义性声明,既可说是声明,又可说是定义。而对“extern int a;” 而言,它是声明而不是定义。一般为了叙述方便,把建立存......
C++ 入门 第四章 4.12.6 用static声明静态外部变量(2008-09-13 19:00:00)
摘要:
有时在程序设计中希望某些外部变量只限于被本文件引用,而不能被其他文件引用。这时可以在定义外部变量时加一个static声明。例如:
file1.cpp file2.cpp
static int a=3; extern int a;
int main ( ) int fun (int n)
{ { ┆
┆ &......
C++ 入门 第四章 4.12.5 用extern声明外部变量(2008-09-12 19:27:00)
摘要:
全局变量(外部变量)是在函数的外部定义的,它的作用域为从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为本文件中各个函数所引用。编译时将全局变量分配在静态存储区。
有时需要用extern来声明全局变量,以扩展全局变量的作用域。
1. 在一个文件内声明全局变量
如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该全局变量,则应该在引用之前用关键字extern对该变量作外部变量声明,表示该变量是一个将在下面定义的全局变量。有了此声明,就可以从声明处起,合法地引用该全局变量,这种声明称为提前引用声明。
例4.14 用extern对外部变量作提前引用声明,以扩展程序文件中的作用域。
#include <iostream>
using namespace std;
int max(int,int); //函数声明
void main( )
{extern int a,b; //对全局变量a,b作提前引用声明
cout<<max(a,b)<<endl;
}
int a=15,b=-7; //定义全局变量a,b
int max(int x,int y)
{int z;
z=x>y?x:y;
return z;
}
运行结果如下:
15
在main后面定义了全局变量a,b,但由于全局变量定义的位置在函数main......
C++ 入门 第四章 4.12.4 用register声明寄存器变量(2008-09-12 19:26:00)
摘要:
一般情况下,变量的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到CPU中的运算器。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。如图4.15所示。
图4.15
为提高执行效率,C++允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。这种变量叫做寄存器变量,用关键字register作声明。例如,可以将例4.14中的fac函数改写如下:
int fac(int n)
{register int i,f=1; //定义i和f是寄存器变量
for(i=1;i<=n;i++) f=f*i;
return f;
}
定义f和i是存放在寄存器的局部变量,如果n的值大,则能节约许多执行时间。
在程序中定义寄存器变量对编译系统只是建议性(而不是强制性)的。当今的优化编译系统能够识别使用频繁的变量,自动地将这些变量放在寄存器中。
......
C++ 入门 第四章 例4.13 输出1~5的阶乘值(2008-09-12 19:25:00)
摘要:
例4.13 输出1~5的阶乘值(即1!,2!,3!,4!,5!)。
#include <iostream>
using namespace std;
int fac(int); //函数声明
int main( )
{int i;
for(i=1;i<=5;i++)
cout<<i<<″!=″<<fac(i)<<endl;
return 0;
}
int fac(int n)
{static int f=1; //f为静态局部变量,函数结束时f的值不释放
f=f*n; //在f原值基础上乘以n
return f;
}
运行结果为
1!=1
2!=2
3!=6
4!=24
5!=120
每次调用fac(i),就输出一个i,同时保留这个i!的值,以便下次再乘(i+1)。
(2) 如果初始化后,变量只被引用而不改变其值,则这时用静态局部变量比较方便,以免每次调用时重新赋值。
但是应该看到,用静态存储要多占内存,而且降低了程序的可读性,当调用次数多时往往弄不清静态局部变量的当前值是什么......
4.12.3 用static声明静态局部变量(2008-09-12 19:24:00)
摘要:
有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量保留上一次函数调用结束时的值。这时就应该指定该局部变量为静态局部变量(static local variable)。
例4.12 静态局部变量的值。
#include <iostream>
using namespace std;
int f(int a) //定义f函数,a为形参
{auto int b=0; //定义b为自动变量
static int c=3; //定义c为静态局部变量
b=b+1;
c=c+1;
return a+b+c;
}
int main( )
{int a=2,i;
for(i=0;i<3;i++)
cout<<f(a)<<″ ″;
cout<<endl;
return 0;
}
运行结果为
7 8 9
先后3次调用f函数时,b和c的......
C++ 入门 第四章 4.12.2 自动变量(2008-09-12 19:22:00)
摘要:
函数中的局部变量,如果不用关键字static加以声明,编译系统对它们是动态地分配存储空间的。函数的形参和在函数中定义的变量(包括在复合语句中定义的变量)都属此类。在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中。在函数调用结束时就自动释放这些空间。如果是在复合语句中定义的变量,则在变量定义时分配存储空间,在复合语句结束时自动释放空间。因此这类局部变量称为自动变量(auto variable)。自动变量用关键字auto作存储类别的声明。例如:
int f(int a) //定义f函数,a为形参
{auto int b,c=3; //定义b和c为整型的自动变量
┆
}
存储类别auto和数据类型int的顺序任意。关键字auto可以省略,如果不写auto,则系统把它默认为自动存储类别,它属于动态存储方式。程序中大多数变量属于自动变量。本书前面各章所介绍的例子中,在函数中定义的变量都没有声明为auto,其实都默认指定为自动变量。在函数体中以下两种写法作用相同:
① auto int b,c=3;
② int b,c=3;
......
C++ 入门 第四章 4.12 变量的存储类别(2008-09-12 19:21:00)
摘要:
4.12.1 动态存储方式与静态存储方式
上一节已介绍了变量的一种属性——作用域,作用域是从空间的角度来分析的,分为全局变量和局部变量。
变量还有另一种属性——存储期(storage duration,也称生命期)。存储期是指变量在内存中的存在期间。这是从变量值存在的时间角度来分析的。存储期可以分为静态存储期(static storage duration)和动态存储期(dynamic storage duration)。这是由变量的静态存储方式和动态存储方式决定的。
所谓静态存储方式是指在程序运行期间,系统对变量分配固定的存储空间。而动态存储方式则是在程序运行期间,系统对变量动态地分配存储空间。
先看一下内存中的供用户使用的存储空间的情况。这个存储空间可以分为三部分,即:
(1) 程序区
(2) 静态存储区
(3) 动态存储区
数据分别存放在静态存储区和动态存储区中。全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储单元,程序执行完毕就释放这些空间。在程序执行过程中它们占据固定的存储单元,而不是动态地进行分配和释放。
在动态存储区中存放以下数据: ①函数形式参数。在调用函数时给形参分配存储空间。②函数中的自动变量(未加static声明的局部变量,详见后面的介绍)。③函数调用时的现场保护和返回地址等。
对以上这些数据,在函数调用开始时分配动态存储空间,函数结束时释放这些空间。在程序执行过程中,这种分配和释放是动态的,如果在一个程序中两次调用同一函数,则要进行两次分配和释放,而两次分配给此函数中局部变量的存储空间地址可能是不相同的。
如果在一个程序中包含若干个函数,每个函数中的局部变量的存储期并不等于整个程序的执行周期,它只是整个程序执行周期的一部分。根据函数调用的情况,系统对局部变量动态地分配和释放存储空间。
在C++中变量除了有数据类型的属性之外,还有存储类别(storage class) 的属性。存储类别指的是数据在内存中存储的方法。存储方法分为静态存储和动态存储两大类。具体包含4种:自动的(auto)、静态的(static)、寄存器的(register)和外部的(exter......
C++ 入门 第四章 4.11 局部变量和全局变量(2008-09-10 14:19:00)
摘要:
4.11.1 局部变量
在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的。同样,在复合语句中定义的变量只在本复合语句范围内有效。这称为局部变量(local variable)。如
float f1(int a) //函数f1
{
int b,c; b、c有效 a有效
┆
}
char f2(int x, int y) //函数f2
{int i,j; i、j有效 x、y有效
┆
}
int main( ) //主函数
{int m,n;
┆
{int p,q; p、q在复合语句中有效 m、n有效
┆
}
}
说明:
(1) 主函数main中定义的变量(m,n)也只在主函数中有效,不会因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其他函数中定义的变量。
(2) 不同函数中可以使用同名的变量,它们代表不同的对象,互不干扰。例如,在f1函数中定义了变量b和c,倘若在f2函数中也定义变量b和c,它们在内存中占不同的单元,不会混淆。
(3) 可以在一个函数内的复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为分程序或程序块。
(4) 形式参数也是局部变量。例如f1函数中的形参a也只在f1函数中有效。其他函数不能调用。
(5) 在函数声明中出现的参数名,其作用范围只在本行的括号内。实际上,编译系统对函数声明中的变量名是忽略的,即使在调用函数时也没有为它们分配存储单元。例如
int max(int a,int b); //函数声明中出现a、b
┆
int max(int x,int y) //函数......