本章导读在第一章中已经介绍过,C源程序是由函数组成的。 虽然在前面各章的程序中都只有一个主函数 main(),但实用程序往往由多个函数组成。函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。C语言中的函数相当于其它高级语言的子程序。 C语言不仅提供了极为丰富的库函数 (如 Turbo C,MS C
都提供了三百多个库函数 ),还允许用户建立自己定义的函数。
用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。
由于采用了函数模块式的结构,C语言易于实现结构化程序设计。使程序的层次结构清晰,便于程序的编写、阅读、调试。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本书目录第 5章 函数与预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本书目录第 5章 函数与预处理本章主要知识点
(1)函数应用的 C程序实例
(2)函数的定义
(3) 函数调用
(4)函数的嵌套调用和递归调用
(5) 内联函数和重载函数
(6)作用域
(7)变量及函数的存储类型
(8) 编译预处理第 5章 函数与预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本章导读
5.2 函数的定义
5.3 函数调用
5.5内联函数和重载函数
5.4 函数的嵌套调用和递归调用
5.1 函数应用的 C程序实例
5.6作用域
5.7变量及函数的存储类型
5.8编译预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.1.1 函数应用的 C程序实例
5.1 函数应用的 C程序实例
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2,C程序实例 (2)
1,C程序实例 (1)
5.1.1 函数应用的 C程序实例
5.1.1 C程序实例( 1)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1.C程序实例 1
【 例 5.1】 简单的函数调用的例子
/*功能:定义两个输出函数并在主函数中调用 */
/*程序代码文件名,l5_1.cpp/
main()
{
printst() ; /* 调用 prigtst 函数 */
print_ hello (); /* 调用 print_hello函数 */
printst() ; /* 调用 prigtst 函数 */
}
printst( ) / * printst 函数 * /
{
程序演示
5.1.1 C程序实例( 1)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
printf( " **************** \n");
}
print_hello( ) /* print_hello函数 */
{
printf(" Hello! \n");
}
程序运行情况如下:
****************
Hello!
****************
程序演示
[例 5.1]程序演示单击运行输入源程序弹出运行结果窗口运行结果返回 例题 返回 本节 目录
5.1.1 C程序实例( 2)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.C程序实例 2
【 例 5.2】 定义一个函数,用于求两个数中的大数 。
/*程序代码文件名,l5_2cpp/
/*功能:定义一个求较大数的函数并在主函数中调用 */
int max(int n1,int n2) /*定义一个函数 max()*/
{ return (n1>n2?n1:n2); }
main()
{ int max(int n1,int n2); /*函数说明 */
int num1,num2;
printf("input two numbers:\n");
scanf("%d%d",&num1,&num2);
printf("max=%d\n",max(num1,num2));
getch(); } /*使程序暂停,按任一键继续 */
程序运行结果为:
input two numbers:
5 6< CR >
max=6 返回 本节 目录程序演示
[例 5.2]程序演示单击运行输入源程序弹出运行结果窗口 运行结果返回 例 题 返回 本节 目录
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.2.2 函数原型
5.2.1 函数的定义
5.2 函数的定义
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.无参函数的一般形式返回 本节 目录类型说明符 函数名 ()
{
类型说明语句
}
其中类型说明符和函数名称为函数头。 类型说明符指明了本函数的类型,函数的类型实际上是函数返回值的类型。 该类型说明符与第二章介绍的各种说明符相同。 函数名是由用户定义的标识符,
函数名后有一个空括号,其中无参数,但括号不可少。 {} 中的内容称为函数体。在函数体中也有类型说明,这是对函数体内部所用到的变量的类型说明。 【 例 4.1】 中的 printst(),print_hello( ) 函数都是无参函数。在很多情况下都不要求无参函数有返回值,因此可以不写类型说明符。
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.有参函数的一般形式类型说明符 函数名 (形式参数表 )
形式参数 类型说明
{
类型说明语句
}
有参函数比无参函数多了两个内容,其一是形式参数表,其二是形式参数类型说明。在形参表中给出的参数称为形式参数,
它们可以是各种类型的变量,各参数之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。 形参既然是变量,当然必须给以类型说明。
返回 本节 目录
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3.说明
( 1)函数定义不允许嵌套。
在C语言中,所有函数(包括主函数 main())都是平行的。一个函数的定义,可以放在程序中的任意位置,主函数 main()之前或之后。但在一个函数的函数体内,不能再定义另一个函数,即不能嵌套定义。
( 2)空函数 ──既无参数、函数体又为空的函数。其一般形式为:
[函数类型 ] 函数名 (void)
{ }
( 3)在老版本 C语言中,参数类型说明允许放在函数说明部分的第 2行单独指定。
返回 本节 目录
5.2.2 函数原型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在 ANSI C新标准中,采用函数原型方式,对被调用函数进行说明,其一般格式如下:
函数类型 函数名 (数据类型 [ 参数名 ][,数据类型 [ 参数名 2]…]) ;
例如
int putlll(int x,int y,int z,int color,char *p) /*说明一个整型函数 */
char *name(void); /*说明一个字符串指什函数
*/
void student(int n,char *str); /*说明一个不返回值的函数
*/
float calculate(); /*说明一个浮点型函数 */
C语言同时又规定,在以下 2种情况下,可以省去对被调用函数的说明:
①当被调用函数的函数定义出现在调用函数之前时。因为在调用之前,编译系统已经知道了被调用函数的函数类型、参数个数、类型和顺序。
②如果在所有函数定义之前,在函数外部(例如文件开始处)预先对各个函数进行了说明,则在调用函数中可缺省对被调用函数的说明。
注意,如果一个函数没有说明就被调用,编译程序并不认为出错,而将此函数默认为整型 (int)函数。因此当一个函数返回其它类型,又没有事先说明,编译时将会出错。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.3.2 函数传值调用
5.3.1 函数调用
5.3 函数调用
5.3.3 函数返回值
5.3.1 函数调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
函数调用的一般形式为,函数名 ([实际参数表 ])
切记,实参的个数、类型和顺序,应该与被调用函数所要求的参数个数、类型和顺序一致,才能正确地进行数据传递。
在C语言中,可以用以下几种方式调用函数:
( 1)函数表达式。函数作为表达式的一项,出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。
( 2)函数语句。 C语言中的函数可以只进行某些操作而不返回函数值,这时的函数调用可作为一条独立的语句。
( 3)函数实参。函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。
返回 本节 目录
5.3.1 函数调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
说明:
( 1)调用函数时,函数名称必须与具有该功能的自定义函数名称完全一致。
( 2)实参在类型上按顺序与形参,必须一一对应和匹配。如果类型不匹配,C编译程序将按赋值兼容的规则进行转换。如果实参和形参的类型不赋值兼容,通常并不给出出错信息,且程序仍然继续执行,只是得不到正确的结果。
( 3)如果实参表中包括多个参数,对实参的求值顺序随系统而异。
有的系统按自左向右顺序求实参的值,有的系统则相反。
返回 本节 目录
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1.函数的参数分为形参和实参两种,作用是实现数据传送。
形参出现在函数定义中,只能在该函数体内使用。发生函数调用时,调用函数把实参的值复制 1份,传送给被调用函数的形参,从而实现调用函数向被调用函数的数据传送。
【 例 5.3】 实参对形参的数据传递。
/*实参对形参的数据传递。 */
/*程序代码文件名,l5_3.cpp/
void main()
{
void so(int n); /*说明函数 */
int n=100; /*定义实参 n,并初始化 */
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
so(n); /*调用函数 */
printf("n_so=%d\n",n); /*输出调用后实参的值,便于进行比较 */
getch();
}
void so(int n)
{
int i;
printf("n_x=%d\n",n); /*输出改变前形参的值 */
for(i=n-1; i>=1; i--) n=n+i; /*改变形参的值 */
printf("n_x=%d\n",n); /*输出改变后形参的值 */
}
程序运行结果为:
n_x=100
n_x=5050
n_x=100
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录说明:
( 1)实参可以是常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。
因此,应预先用赋值、输入等办法,使实参获得确定的值。
( 2)形参变量只有在被调用时,才分配内存单元;调用结束时,
即刻释放所分配的内存单元。
因此,形参只有在该函数内有效。调用结束,返回调用函数后,
则不能再使用该形参变量。
( 3)实参对形参的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
( 4)实参和形参占用不同的内存单元,即使同名也互不影响。
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2,数组元素作为函数参数数组元素就是下标变量,它与普通变量并无区别。数组元素只能用作函数实参,其用法与普通变量完全相同:在发生函数调用时,把数组元素的值传送给形参,实现单向值传送。
说明:
( 1)用数组元素作实参时,只要数组类型和函数的形参类型一致即可,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。
( 2)在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送,是把实参变量的值赋予形参变量。
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
3.数组名作为函数参数用数组名作函数参数与用数组元素作实参有几点不同:
(1),用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是下标变量。
用数组名作函数参数时,则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。当形参和实参二者不一致时,即会发生错误。
(2),在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么,数据的传送是如何实现的呢? 在第三章中我们曾介绍过,数组名就是数组的首地址。
因此在数组名作函数参数时所进行的传送只是 地址的传送,
也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。
【 例 5.4】 数组 a中存放了一个学生 5门课程的成绩,求平均成绩。
/*程序代码文件名,l5_4.cpp/
/*功能:数组名作为函数实参 */
float aver(float a[5])
{
int i;
float av,s=a[0];
for(i=1;i<5;i++)
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
s=s+a[i];
av=s/5;
return av;
}
void main()
{
float sco[5],av;
int i;
printf("\ninput 5 scores,");
for(i=0;i<5;i++)
scanf("%f",&sco[i]);
av=aver(sco);
printf("average score is %5.2f",av);
}
}
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录程序运行结果为,
input 5 scores:89 65.0 78.8 99 90.5<CR>
average score is 84.46
程序说明,
本程序首先定义了一个实型函数 aver,有一个形参为实型数组 a,长度为 5。在函数 aver中,把各元素值相加求出平均值,返回给主函数。主函数 main 中首先完成数组 sco的输入,然后以 sco作为实参调用 aver函数,
函数返回值送 av,最后输出 av值。 从运行情况可以看出,程序实现了所要求的功能用数组名作为函数参数时还应 注意 以下几点:
a 形参数组和实参数组的类型必须一致,否则将引起错误。
b 形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,
虽不至于出现语法错误 (编译能通过 ),但程序执行结果将与实际不符,
这是应予以注意的。
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1函数返回值与 return语句。
有参函数的返回值,是通过函数中的 return语句来获得的。
( 1) return语句的一般格式,return ( 返回值表达式 );
( 2) return语句的功能:返回调用函数,并将“返回值表达式”的值带给调用函数。
【例 5.5】 函数返回值的例子
/*程序代码文件名,l5_5.cpp/
/*功能:求最大值 */
int maxmum(int x,int y,int z); /*说明一个用户自定义函数 */
main()
{
int i,j,k,max;
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
scanf("%d%d%d",&i,&j,&k);
max=maxmum(i,j,k); /*调用子函数,并将返回值赋给
max*/
printf("The maxmum value is %d\n",max);
}
maxmum(int x,int y,int z)
{
int max;
max=x>y?x:y; /*求最大值 */
max=max>z?max:z;
return(max); /*返回最大值 */
}
程序运行情况如下:
77 99 56 <CR>
The maxmum value is 99
value is 99
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2 关于返回语句的说明
(1)函数的返回值只能有一个。
(2)当函数中不需要指明返回值时,可以写成:
return;
也可以不写。函数运行到右花括号自然结束。
(3)一个函数体内可以有多个返回语句,不论执行到哪一个,
函数都结束,回到主调函数。
(4)当函数没有指明返回值,即 return; 或没有返回语句时,函数执行后实际上不是没有返回值,而是返回一个不确定的值,有可能给程序带来某种意外的影响。
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
3、关于函数返回值的类型函数定义时的类型就是函数返回值的类型。从理论上,C语言要求函数定义的类型应当与返回语句中表达式的类型保持一致。当两者不一致时,系统自动进行转换,将函数返回语句中表达式的类型转换为函数定义时的类型。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.4.2 函数的递归调用
5.4.1 函数的嵌套调用
5.4 函数的嵌套调用和递归调用
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。 但是C语言允许在一个函数的定义中出现对另一个函数的调用 。 这样就出现了函数的嵌套调用。 即在被调函数中又调用其它函数。其关系可表示如下图,其执行过程是:执行 main函数中调用 f1函数的语句时,即转去执行 f1函数,在 f1函数中调用 f2 函数时,又转去执行 f2函数,f2函数执行完毕返回 f1函数的断点继续执行,f1 函数执行完毕返回 main函数的断点继续执行返回 本节 目录
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
【 例 5.6】 计算 s=1k+2k+3k+……+N k
/*程序代码文件名,l5_6.cpp /
/*功能:函数的嵌套调用 */
#define K 4
#define N 5
long f1(int n,int k) /*计算 n的 k次方 */
{ long power=n;
int i;
for(i=1;i<k;i++) power *= n;
return power;
}
long f2(int n,int k) /*计算 1到 n的 k次方之累加和 */
{ long sum=0;
返回 本节 目录
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
int i;
for(i=1;i<=n;i++) sum += f1(i,k);
return sum;
}
main()
{ printf("Sum of %d powers of integers from 1 to %ld = ",K,N);
printf("%d\n",f2(N,K));
getch();
}
程序运行结果为,Sum of 4 powers of integers from 1 to 5=979
说明,本题编写了两个函数,一个是用来计算 n的 k次方的函数 f1,另一个是用来计算 1到 n的 k次方之累加和函数 f2。主函数先调 f1计算 n的 k次方,
再在 f1中以为 n的 k次方实参,调用 f2计算其累加和,然后返回 f1,再返回主函数。
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
一个函数在它的函数体内调用它自身称为递归调用。 这种函数称为递归函数。在递归调用中,主调函数又是被调函数。
执行递归函数将反复调用其自身。 例如有函数 f如下:
int f (int x)
{
int y;
z=f(y);
return z;
}
这个函数是一个递归函数。 但是运行该函数将无休止地调用其自身,这当然是不正确的。为了防止递归调用无终止地进行,
必须在函数内有终止递归调用的手段。常用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
例 5.7】 用递归法计算 n!。
/*程序代码文件名,l5_7.cpp /
/*功能:通过函数的递归调用计算阶乘 */
long power(int n)
{
long f;
if(n>1) f=power(n-1)*n;
else f=1;
return(f);
}
main()
{
int n;
long y;
printf("input a inteager number:");
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
scanf("%d",&n);
y=power(n);
printf("%d!=%ld\n",n,y);
getch();
}
程序运行情况如下:
input a inteager number,5 <CR>
5!=120
程序说明,
程序中给出的函数 power是一个递归函数。主函数调用 power 后即进入函数 power执行,如果 n<0,n==0或 n=1时都将结束函数的执行,否则就递归调用 power函数自身。由于每次递归调用的实参为 n-1,即把 n-1 的值赋予形参 n,最后当 n-1的值为 1时再作递归调用,形参 n的值也为 1,将使递归终止。然后可逐层退回。
返回 本节 目录
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本章目录
5.5.2重载函数
5.5.1内联函数
5.5内联函数和重载函数
5.5.1 内联函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录调用函数时需要一定的时间,如果有的函数需要频繁使用,
则所用时间会很长,从而降低程序的执行效率。 C 十十提供一种提高效率的方法,即在编译时将所调用函数的代码嵌入到主调函数中。 这种嵌入到主调函数中的函数称为内联函数 ( inline
function ),又称内嵌函数。
指定内联函数的方法很简单,只需在函数首行的左端加一个关键字 inline 即可。
【 例 5.8】 将函数指定为内联函数。
/*程序代码文件名,l5_8.cpp /
/*功能:通过内置函数求 3 个整数中的最大者 */
# include <iostream,h>
inline int max(int a,int b,int c) //这是一个内置函数,求 3 个整数中的最大者
{
if (b>a) a = b;
5.5.1 内联函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
if (c>a) a = c;
return a;
}
void main( )
{
int i = 7,j=10,k = 25,m ;
m = max(i,j,k);
cout<<”max =” <<m<<endl;
}
由于在定义函数时指定它为内联函数,因此编译系统在遇到函数调用
max(i,j,k)时,就用 max 函数体的代码代替 max(i,j,k),同时将实参代替形参。这样,m = max(i,j,k);就被置换成
if(j>i) i = j;
if(k>i) i = k;
m = i;
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在 C++中用到了插入运算符<<和提取运算符>>。 这两个运算符本来是左移运算符和右移运算符,现在把它作为输入输出运算符。即允许一个运算符用于不同场合,有不同的含义,
这就叫运算符的“重载” ( overloading ),即重新赋予它新的含义。
函数也可以重载。 C + +允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载,即一个函数名多用。
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【 例 5.9】 求 n 个整数中的最大数。 n 的值为 2 和 3 。
/*程序代码文件名,l5_9.cpp /
/*功能:通过函数的重载求 n 个整数中的最大者 */
# include <iostream,h>
int max(int a,int b,int c) //求 3 个整数中的最大者
{
if (b>a) a = b;
if (c>a) a = c;
return a; }
int max (int a,int b) //求 2 个整数中的最大者
{
if (a>b) return a;
else return b*}
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
void main( )
{
int a=7,b= 4,c = 11;
cout < <max (a,b,c ) < <endl ; //输出 3 个整数中的最大者
cout<<max(a,b)<<endl; //输出 2 个整数中的最大者
}
运行结果如下:
11
7
两次调用 max 函数的参数个数不同,系统会根据参数的个数找到与之匹配的函数并调用它。
参数的个数和类型可以都不同。应当 注意,重载函数的参数个数或类型必须至少有一者不同,函数返回值类型可以相同也可以不同。但不允许参数个数和类型都相同而只有返回值类型不同,因为系统无法从函数的调用形式上判断哪一个函数与之匹配。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.6.2全局变量和局部变量
5.6.1 作用域
5.6作用域
5.6.1 作用域
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。
这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。这种变量有效性的范围称变量的作用域。不仅对于形参变量,C语言中所有的量都有自己的作用域。变量说明的方式不同,其作用域也不同。 C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,局部变量返回 本节 目录在一个函数内部说明的变量是内部变量,它只在该函数范围内有效。也就是说,只有在包含变量说明的函数内部,才能使用被说明的变量,在此函数之外就不能使用这些变量了。所以内部变量也称“局部变量”。例如:
int f1(int a) /*函数 f1*/
{ int b,c;
…… } /*a,b,c作用域:仅限于函数 f1()中 */
int f2(int x) /*函数 f2*/
{ int y,z;
…… } /*x,y,z作用域:仅限于函数 f2()中 */
main()
{ int m,n;
…… } /*m,n作用域:仅限于函数 main()中 */
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.全局变量返回 本节 目录全局变量也称为外部变量,它是在函数外部定义的变量。 它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局变量说明。 只有在函数内经过说明的全局变量才能使用。全局变量的说明符为
extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。 例如:
int a,b; /*外部变量 */
void f1() /*函数 f1*/
{
……
}
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
float x,y; /*外部变量 */
int fz() /*函数 fz*/
{
……
}
main() /*主函数 */
{
……
} /*全局变量 x,y作用域 全局变量 a,b作用域 */
从上例可以看出 a,b,x,y 都是在函数外部定义的外部变量,都是全局变量。但 x,y 定义在函数 f1之后,而在 f1内又无对 x,y的说明,
所以它们在 f1内无效。 a,b定义在源程序最前面,因此在 f1,f2及
main内不加说明也可使用。
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【例 5.10】输入长方体的长宽高 l,w,h。求体积及三个面 x*y,x*z,y*z
的面积。
/*程序代码文件名,l5_10.cpp /
/*功能:求长方体体积及三个面 x*y,x*z,y*z的面积。 */
int s1,s2,s3;
int vs( int a,int b,int c)
{
int v;
v=a*b*c;
s1=a*b;
s2=b*c;
s3=a*c;
return v;
}
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
main()
{
int v,l,w,h;
printf("\ninput length,width and height,");
scanf("%d%d%d",&l,&w,&h);
v=vs(l,w,h);
printf("v=%d s1=%d s2=%d s3=%d\n",v,s1,s2,s3);
}
程序运行结果如下:
input length,width and height:4 5 6 <CR>
v=120 s1=20 s2=30 s3=24
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录程序说明,
本程序中定义了三个外部变量 s1,s2,s3,用来存放三个面积,其作用域为整个程序。函数 vs用来求正方体体积和三个面积,函数的返回值为体积 v。由主函数完成长宽高的输入及结果输出。
由于C语言规定函数返回值只有一个,当需要增加函数的返回数据时,用外部变量是一种很好的方式。本例中,如不使用外部变量,在主函数中就不可能取得 v,s1,s2,s3四个值。而采用了外部变量,在函数 vs中求得的 s1,s2,s3值在 main 中仍然有效。因此外部变量是实现函数之间数据通讯的有效手段。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.7.2函数的存储类型
5.7.1变量的存储类型
5.7变量及函数的存储类型
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.自动变量返回 本节 目录自动变量的类型说明符为 auto
这种存储类型是C语言程序中使用最广泛的一种类型。
C语言规定,函数内凡未加存储类型说明的变量均视为自动变量,
也就是说自动变量可省去说明符 auto。 在前面各章的程序中所定义的变量凡未加存储类型说明符的都是自动变量。例如:
{ int a,b,k;
char c;
……
}等价于:
{ auto int a,b,k;
auto char c;
……
}
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录自动变量具有以下特点:
(1) 自动变量的作用域仅限于定义该变量的个体内。
(2) 自动变量属于动态存储方式,只有在使用它,即定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。
(3) 由于自动变量的作用域和生存期都局限于定义它的个体内 ( 函数或复合语句内 ),因此不同的个体中允许使用同名的变量而不会混淆。
(4) 对构造类型的自动变量如数组等,不可作初始化赋值。
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.外部变量返回 本节 目录外部变量的类型说明符为 extern。
在前面介绍全局变量时已介绍过外部变量。这里再补充说明外部变量的几个特点:
(1) 外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。
( 2)当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其它的源文件中也有效。
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3.静态变量返回 本节 目录静态变量的类型说明符是 static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,
例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。 对于自动变量,前面已经介绍它属于动态存储方式。
但是也可以用 static定义它为静态自动变量,或称静态局部变量。
4.寄存器变量寄存器变量的说明符是 register 。这种变量存放在 CPU的寄存器中,
使用时,不需要访问内存,而直接从寄存器中读写,这样可提高效率。
5.7.2 函数的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,内部函数(又称静态函数)
返回 本节 目录如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
定义一个内部函数,只需在函数类型前再加一个,static”关键字即可,如下所示:
static 函数类型 函数名 (函数参数表 )
{……}
关键字,static”,译成中文就是“静态的”,所以内部函数又称静态函数。但此处,static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
5.7.2 函数的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.外部函数返回 本节 目录外部函数的定义:在定义函数时,如果没有加关键字,static”,冠以关键字,extern”,表示此函数是外部函数:
[extern] 函数类型 函数名 (函数参数表 )
{……}
调用外部函数时,需要对其进行说明:
[extern] 函数类型 函数名 (参数类型表 )[,函数名 2(参数类型表
2)……] ;
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.8.2 文件包含
5.8.1 宏定义
5.8 编译预处理
5.8.3 条件编译
5.8.1 宏定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.无参宏定义返回 本节 目录无参宏的宏名后不带参数。
其定义的一般形式为,#define 标识符 字符串其中的,#”表示这是一条预处理命令。凡是以,#”开头的均为预处理命令。
,define”为宏定义命令。,标识符”为所定义的宏名。“字符串”
可以是常数、表达式、格式串等。
在前面介绍过的符号常量的定义就是一种无参宏定义。 此外,常对程序中反复使用的表达式进行宏定义。
例如,# define M (y*y+3*y) 定义 M 为表达式 (y*y+3*y)。在编写源程序时,所有的 (y*y+3*y)都可由 M代替,而对源程序作编译时,将先由预处理程序进行宏代换,即用 (y*y+3*y)表达式去置换所有的宏名 M,然后再进行编译。
5.8.1 宏定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.带参宏定义返回 本节 目录
C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,
而且要用实参去代换形参。
带参宏定义的一般形式为,#define 宏名 (形参表 ) 字符串在字符串中含有各个形参。
带参宏调用的一般形式为,宏名 (实参表 );
例如:
#define M(y) y*y+3*y /*宏定义 */
,
k=M(5); /*宏调用 */
,
在宏调用时,用实参 5去代替形参 y,经预处理宏展开后的语句为,k=5*5+3*5
5.8.2 文件包含
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录文件包含命令行的一般形式为,#include"文件名 "在前面我们已多次用此命令包含过库函数的头文件。例如:
#include"stdio.h"
#include"math.h"
文件包含命令的功能,是把指定的文件插入该命令行位置取代该命令行,
从而把指定的文件和当前的源程序文件连成一个源文件。
对文件包含命令还要说明以下几点:
(1),包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找 (包含目录是由用户在设置环境时设置的 ),而不在源文件目录去查找; 使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。
用户编程时可根据自己文件所在的目录来选择某一种命令形式。
(2),一个 include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个 include命令。
(3),文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,第一种形式:
返回 本节 目录
#ifdef 标识符程序段 1
#else
程序段 2
#endif
它的功能是,如果标识符已被 #define命令定义过则对程序段 1进行编译;否则对程序段 2进行编译。 如果没有程序段 2(它为空 ),本格式中的 #else可以没有,即可以写为:
#ifdef 标识符程序段 #endif
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2,第 二 种形式:
返回 本节 目录
#ifndef 标识符程序段 1
#else
程序段 2
#endif
与第一种形式的区别是将,ifdef”改为,ifndef”。
它的功能是:如果标识符未被 #define命令定义过则对程序段 1进行编译,否则对程序段 2进行编译。这与第一种形式的功能正相反。
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3,第三种形式:
返回 本节 目录
#if 常量表达式程序段 1
#else
程序段 2
#endif
它的功能是,如常量表达式的值为真 (非 0),则对程序段 1 进行编译,否则对程序段 2进行编译。因此可以使程序在不同条件下,完成不同的功能
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【例 5.11】 计算圆面积
/*程序代码文件名,l5_11.cpp /
#define R 1
main()
{
float c,r,s;
printf ("input a number,");
scanf("%f",&c);
#if R
r=3.14159*c*c;
printf("area of round is,%f\n",r);
#else
s=c*c;
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
printf("area of square is,%f\n",s);
#endif
}
运行的结果如下,
input a number:10<CR>
area of round is:314.158997
程序说明,本例中采用了第三种形式的条件编译。在程序第一行宏定义中,定义 R为 1,因此在条件编译时,常量表达式的值为真,故计算并输出圆面积。
上面介绍的条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段 1或程序段 2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。
都提供了三百多个库函数 ),还允许用户建立自己定义的函数。
用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。
由于采用了函数模块式的结构,C语言易于实现结构化程序设计。使程序的层次结构清晰,便于程序的编写、阅读、调试。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本书目录第 5章 函数与预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本书目录第 5章 函数与预处理本章主要知识点
(1)函数应用的 C程序实例
(2)函数的定义
(3) 函数调用
(4)函数的嵌套调用和递归调用
(5) 内联函数和重载函数
(6)作用域
(7)变量及函数的存储类型
(8) 编译预处理第 5章 函数与预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本章导读
5.2 函数的定义
5.3 函数调用
5.5内联函数和重载函数
5.4 函数的嵌套调用和递归调用
5.1 函数应用的 C程序实例
5.6作用域
5.7变量及函数的存储类型
5.8编译预处理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.1.1 函数应用的 C程序实例
5.1 函数应用的 C程序实例
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2,C程序实例 (2)
1,C程序实例 (1)
5.1.1 函数应用的 C程序实例
5.1.1 C程序实例( 1)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1.C程序实例 1
【 例 5.1】 简单的函数调用的例子
/*功能:定义两个输出函数并在主函数中调用 */
/*程序代码文件名,l5_1.cpp/
main()
{
printst() ; /* 调用 prigtst 函数 */
print_ hello (); /* 调用 print_hello函数 */
printst() ; /* 调用 prigtst 函数 */
}
printst( ) / * printst 函数 * /
{
程序演示
5.1.1 C程序实例( 1)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
printf( " **************** \n");
}
print_hello( ) /* print_hello函数 */
{
printf(" Hello! \n");
}
程序运行情况如下:
****************
Hello!
****************
程序演示
[例 5.1]程序演示单击运行输入源程序弹出运行结果窗口运行结果返回 例题 返回 本节 目录
5.1.1 C程序实例( 2)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.C程序实例 2
【 例 5.2】 定义一个函数,用于求两个数中的大数 。
/*程序代码文件名,l5_2cpp/
/*功能:定义一个求较大数的函数并在主函数中调用 */
int max(int n1,int n2) /*定义一个函数 max()*/
{ return (n1>n2?n1:n2); }
main()
{ int max(int n1,int n2); /*函数说明 */
int num1,num2;
printf("input two numbers:\n");
scanf("%d%d",&num1,&num2);
printf("max=%d\n",max(num1,num2));
getch(); } /*使程序暂停,按任一键继续 */
程序运行结果为:
input two numbers:
5 6< CR >
max=6 返回 本节 目录程序演示
[例 5.2]程序演示单击运行输入源程序弹出运行结果窗口 运行结果返回 例 题 返回 本节 目录
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.2.2 函数原型
5.2.1 函数的定义
5.2 函数的定义
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.无参函数的一般形式返回 本节 目录类型说明符 函数名 ()
{
类型说明语句
}
其中类型说明符和函数名称为函数头。 类型说明符指明了本函数的类型,函数的类型实际上是函数返回值的类型。 该类型说明符与第二章介绍的各种说明符相同。 函数名是由用户定义的标识符,
函数名后有一个空括号,其中无参数,但括号不可少。 {} 中的内容称为函数体。在函数体中也有类型说明,这是对函数体内部所用到的变量的类型说明。 【 例 4.1】 中的 printst(),print_hello( ) 函数都是无参函数。在很多情况下都不要求无参函数有返回值,因此可以不写类型说明符。
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.有参函数的一般形式类型说明符 函数名 (形式参数表 )
形式参数 类型说明
{
类型说明语句
}
有参函数比无参函数多了两个内容,其一是形式参数表,其二是形式参数类型说明。在形参表中给出的参数称为形式参数,
它们可以是各种类型的变量,各参数之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。 形参既然是变量,当然必须给以类型说明。
返回 本节 目录
5.2.1 函数的定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3.说明
( 1)函数定义不允许嵌套。
在C语言中,所有函数(包括主函数 main())都是平行的。一个函数的定义,可以放在程序中的任意位置,主函数 main()之前或之后。但在一个函数的函数体内,不能再定义另一个函数,即不能嵌套定义。
( 2)空函数 ──既无参数、函数体又为空的函数。其一般形式为:
[函数类型 ] 函数名 (void)
{ }
( 3)在老版本 C语言中,参数类型说明允许放在函数说明部分的第 2行单独指定。
返回 本节 目录
5.2.2 函数原型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在 ANSI C新标准中,采用函数原型方式,对被调用函数进行说明,其一般格式如下:
函数类型 函数名 (数据类型 [ 参数名 ][,数据类型 [ 参数名 2]…]) ;
例如
int putlll(int x,int y,int z,int color,char *p) /*说明一个整型函数 */
char *name(void); /*说明一个字符串指什函数
*/
void student(int n,char *str); /*说明一个不返回值的函数
*/
float calculate(); /*说明一个浮点型函数 */
C语言同时又规定,在以下 2种情况下,可以省去对被调用函数的说明:
①当被调用函数的函数定义出现在调用函数之前时。因为在调用之前,编译系统已经知道了被调用函数的函数类型、参数个数、类型和顺序。
②如果在所有函数定义之前,在函数外部(例如文件开始处)预先对各个函数进行了说明,则在调用函数中可缺省对被调用函数的说明。
注意,如果一个函数没有说明就被调用,编译程序并不认为出错,而将此函数默认为整型 (int)函数。因此当一个函数返回其它类型,又没有事先说明,编译时将会出错。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.3.2 函数传值调用
5.3.1 函数调用
5.3 函数调用
5.3.3 函数返回值
5.3.1 函数调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
函数调用的一般形式为,函数名 ([实际参数表 ])
切记,实参的个数、类型和顺序,应该与被调用函数所要求的参数个数、类型和顺序一致,才能正确地进行数据传递。
在C语言中,可以用以下几种方式调用函数:
( 1)函数表达式。函数作为表达式的一项,出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。
( 2)函数语句。 C语言中的函数可以只进行某些操作而不返回函数值,这时的函数调用可作为一条独立的语句。
( 3)函数实参。函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。
返回 本节 目录
5.3.1 函数调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
说明:
( 1)调用函数时,函数名称必须与具有该功能的自定义函数名称完全一致。
( 2)实参在类型上按顺序与形参,必须一一对应和匹配。如果类型不匹配,C编译程序将按赋值兼容的规则进行转换。如果实参和形参的类型不赋值兼容,通常并不给出出错信息,且程序仍然继续执行,只是得不到正确的结果。
( 3)如果实参表中包括多个参数,对实参的求值顺序随系统而异。
有的系统按自左向右顺序求实参的值,有的系统则相反。
返回 本节 目录
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1.函数的参数分为形参和实参两种,作用是实现数据传送。
形参出现在函数定义中,只能在该函数体内使用。发生函数调用时,调用函数把实参的值复制 1份,传送给被调用函数的形参,从而实现调用函数向被调用函数的数据传送。
【 例 5.3】 实参对形参的数据传递。
/*实参对形参的数据传递。 */
/*程序代码文件名,l5_3.cpp/
void main()
{
void so(int n); /*说明函数 */
int n=100; /*定义实参 n,并初始化 */
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
so(n); /*调用函数 */
printf("n_so=%d\n",n); /*输出调用后实参的值,便于进行比较 */
getch();
}
void so(int n)
{
int i;
printf("n_x=%d\n",n); /*输出改变前形参的值 */
for(i=n-1; i>=1; i--) n=n+i; /*改变形参的值 */
printf("n_x=%d\n",n); /*输出改变后形参的值 */
}
程序运行结果为:
n_x=100
n_x=5050
n_x=100
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录说明:
( 1)实参可以是常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。
因此,应预先用赋值、输入等办法,使实参获得确定的值。
( 2)形参变量只有在被调用时,才分配内存单元;调用结束时,
即刻释放所分配的内存单元。
因此,形参只有在该函数内有效。调用结束,返回调用函数后,
则不能再使用该形参变量。
( 3)实参对形参的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
( 4)实参和形参占用不同的内存单元,即使同名也互不影响。
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2,数组元素作为函数参数数组元素就是下标变量,它与普通变量并无区别。数组元素只能用作函数实参,其用法与普通变量完全相同:在发生函数调用时,把数组元素的值传送给形参,实现单向值传送。
说明:
( 1)用数组元素作实参时,只要数组类型和函数的形参类型一致即可,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。
( 2)在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送,是把实参变量的值赋予形参变量。
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
3.数组名作为函数参数用数组名作函数参数与用数组元素作实参有几点不同:
(1),用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是下标变量。
用数组名作函数参数时,则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。当形参和实参二者不一致时,即会发生错误。
(2),在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么,数据的传送是如何实现的呢? 在第三章中我们曾介绍过,数组名就是数组的首地址。
因此在数组名作函数参数时所进行的传送只是 地址的传送,
也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。
【 例 5.4】 数组 a中存放了一个学生 5门课程的成绩,求平均成绩。
/*程序代码文件名,l5_4.cpp/
/*功能:数组名作为函数实参 */
float aver(float a[5])
{
int i;
float av,s=a[0];
for(i=1;i<5;i++)
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
s=s+a[i];
av=s/5;
return av;
}
void main()
{
float sco[5],av;
int i;
printf("\ninput 5 scores,");
for(i=0;i<5;i++)
scanf("%f",&sco[i]);
av=aver(sco);
printf("average score is %5.2f",av);
}
}
5.3.2 函数传值调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录程序运行结果为,
input 5 scores:89 65.0 78.8 99 90.5<CR>
average score is 84.46
程序说明,
本程序首先定义了一个实型函数 aver,有一个形参为实型数组 a,长度为 5。在函数 aver中,把各元素值相加求出平均值,返回给主函数。主函数 main 中首先完成数组 sco的输入,然后以 sco作为实参调用 aver函数,
函数返回值送 av,最后输出 av值。 从运行情况可以看出,程序实现了所要求的功能用数组名作为函数参数时还应 注意 以下几点:
a 形参数组和实参数组的类型必须一致,否则将引起错误。
b 形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,
虽不至于出现语法错误 (编译能通过 ),但程序执行结果将与实际不符,
这是应予以注意的。
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
1函数返回值与 return语句。
有参函数的返回值,是通过函数中的 return语句来获得的。
( 1) return语句的一般格式,return ( 返回值表达式 );
( 2) return语句的功能:返回调用函数,并将“返回值表达式”的值带给调用函数。
【例 5.5】 函数返回值的例子
/*程序代码文件名,l5_5.cpp/
/*功能:求最大值 */
int maxmum(int x,int y,int z); /*说明一个用户自定义函数 */
main()
{
int i,j,k,max;
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
scanf("%d%d%d",&i,&j,&k);
max=maxmum(i,j,k); /*调用子函数,并将返回值赋给
max*/
printf("The maxmum value is %d\n",max);
}
maxmum(int x,int y,int z)
{
int max;
max=x>y?x:y; /*求最大值 */
max=max>z?max:z;
return(max); /*返回最大值 */
}
程序运行情况如下:
77 99 56 <CR>
The maxmum value is 99
value is 99
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
2 关于返回语句的说明
(1)函数的返回值只能有一个。
(2)当函数中不需要指明返回值时,可以写成:
return;
也可以不写。函数运行到右花括号自然结束。
(3)一个函数体内可以有多个返回语句,不论执行到哪一个,
函数都结束,回到主调函数。
(4)当函数没有指明返回值,即 return; 或没有返回语句时,函数执行后实际上不是没有返回值,而是返回一个不确定的值,有可能给程序带来某种意外的影响。
5.3.3函数返回值
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
3、关于函数返回值的类型函数定义时的类型就是函数返回值的类型。从理论上,C语言要求函数定义的类型应当与返回语句中表达式的类型保持一致。当两者不一致时,系统自动进行转换,将函数返回语句中表达式的类型转换为函数定义时的类型。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.4.2 函数的递归调用
5.4.1 函数的嵌套调用
5.4 函数的嵌套调用和递归调用
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。 但是C语言允许在一个函数的定义中出现对另一个函数的调用 。 这样就出现了函数的嵌套调用。 即在被调函数中又调用其它函数。其关系可表示如下图,其执行过程是:执行 main函数中调用 f1函数的语句时,即转去执行 f1函数,在 f1函数中调用 f2 函数时,又转去执行 f2函数,f2函数执行完毕返回 f1函数的断点继续执行,f1 函数执行完毕返回 main函数的断点继续执行返回 本节 目录
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
【 例 5.6】 计算 s=1k+2k+3k+……+N k
/*程序代码文件名,l5_6.cpp /
/*功能:函数的嵌套调用 */
#define K 4
#define N 5
long f1(int n,int k) /*计算 n的 k次方 */
{ long power=n;
int i;
for(i=1;i<k;i++) power *= n;
return power;
}
long f2(int n,int k) /*计算 1到 n的 k次方之累加和 */
{ long sum=0;
返回 本节 目录
5.4.1 函数的嵌套调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
int i;
for(i=1;i<=n;i++) sum += f1(i,k);
return sum;
}
main()
{ printf("Sum of %d powers of integers from 1 to %ld = ",K,N);
printf("%d\n",f2(N,K));
getch();
}
程序运行结果为,Sum of 4 powers of integers from 1 to 5=979
说明,本题编写了两个函数,一个是用来计算 n的 k次方的函数 f1,另一个是用来计算 1到 n的 k次方之累加和函数 f2。主函数先调 f1计算 n的 k次方,
再在 f1中以为 n的 k次方实参,调用 f2计算其累加和,然后返回 f1,再返回主函数。
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
一个函数在它的函数体内调用它自身称为递归调用。 这种函数称为递归函数。在递归调用中,主调函数又是被调函数。
执行递归函数将反复调用其自身。 例如有函数 f如下:
int f (int x)
{
int y;
z=f(y);
return z;
}
这个函数是一个递归函数。 但是运行该函数将无休止地调用其自身,这当然是不正确的。为了防止递归调用无终止地进行,
必须在函数内有终止递归调用的手段。常用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
例 5.7】 用递归法计算 n!。
/*程序代码文件名,l5_7.cpp /
/*功能:通过函数的递归调用计算阶乘 */
long power(int n)
{
long f;
if(n>1) f=power(n-1)*n;
else f=1;
return(f);
}
main()
{
int n;
long y;
printf("input a inteager number:");
返回 本节 目录
5.4.2 函数的递归调用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
scanf("%d",&n);
y=power(n);
printf("%d!=%ld\n",n,y);
getch();
}
程序运行情况如下:
input a inteager number,5 <CR>
5!=120
程序说明,
程序中给出的函数 power是一个递归函数。主函数调用 power 后即进入函数 power执行,如果 n<0,n==0或 n=1时都将结束函数的执行,否则就递归调用 power函数自身。由于每次递归调用的实参为 n-1,即把 n-1 的值赋予形参 n,最后当 n-1的值为 1时再作递归调用,形参 n的值也为 1,将使递归终止。然后可逐层退回。
返回 本节 目录
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回本章目录
5.5.2重载函数
5.5.1内联函数
5.5内联函数和重载函数
5.5.1 内联函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录调用函数时需要一定的时间,如果有的函数需要频繁使用,
则所用时间会很长,从而降低程序的执行效率。 C 十十提供一种提高效率的方法,即在编译时将所调用函数的代码嵌入到主调函数中。 这种嵌入到主调函数中的函数称为内联函数 ( inline
function ),又称内嵌函数。
指定内联函数的方法很简单,只需在函数首行的左端加一个关键字 inline 即可。
【 例 5.8】 将函数指定为内联函数。
/*程序代码文件名,l5_8.cpp /
/*功能:通过内置函数求 3 个整数中的最大者 */
# include <iostream,h>
inline int max(int a,int b,int c) //这是一个内置函数,求 3 个整数中的最大者
{
if (b>a) a = b;
5.5.1 内联函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
if (c>a) a = c;
return a;
}
void main( )
{
int i = 7,j=10,k = 25,m ;
m = max(i,j,k);
cout<<”max =” <<m<<endl;
}
由于在定义函数时指定它为内联函数,因此编译系统在遇到函数调用
max(i,j,k)时,就用 max 函数体的代码代替 max(i,j,k),同时将实参代替形参。这样,m = max(i,j,k);就被置换成
if(j>i) i = j;
if(k>i) i = k;
m = i;
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在 C++中用到了插入运算符<<和提取运算符>>。 这两个运算符本来是左移运算符和右移运算符,现在把它作为输入输出运算符。即允许一个运算符用于不同场合,有不同的含义,
这就叫运算符的“重载” ( overloading ),即重新赋予它新的含义。
函数也可以重载。 C + +允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载,即一个函数名多用。
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【 例 5.9】 求 n 个整数中的最大数。 n 的值为 2 和 3 。
/*程序代码文件名,l5_9.cpp /
/*功能:通过函数的重载求 n 个整数中的最大者 */
# include <iostream,h>
int max(int a,int b,int c) //求 3 个整数中的最大者
{
if (b>a) a = b;
if (c>a) a = c;
return a; }
int max (int a,int b) //求 2 个整数中的最大者
{
if (a>b) return a;
else return b*}
5.5.2重载函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
void main( )
{
int a=7,b= 4,c = 11;
cout < <max (a,b,c ) < <endl ; //输出 3 个整数中的最大者
cout<<max(a,b)<<endl; //输出 2 个整数中的最大者
}
运行结果如下:
11
7
两次调用 max 函数的参数个数不同,系统会根据参数的个数找到与之匹配的函数并调用它。
参数的个数和类型可以都不同。应当 注意,重载函数的参数个数或类型必须至少有一者不同,函数返回值类型可以相同也可以不同。但不允许参数个数和类型都相同而只有返回值类型不同,因为系统无法从函数的调用形式上判断哪一个函数与之匹配。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.6.2全局变量和局部变量
5.6.1 作用域
5.6作用域
5.6.1 作用域
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。
这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。这种变量有效性的范围称变量的作用域。不仅对于形参变量,C语言中所有的量都有自己的作用域。变量说明的方式不同,其作用域也不同。 C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,局部变量返回 本节 目录在一个函数内部说明的变量是内部变量,它只在该函数范围内有效。也就是说,只有在包含变量说明的函数内部,才能使用被说明的变量,在此函数之外就不能使用这些变量了。所以内部变量也称“局部变量”。例如:
int f1(int a) /*函数 f1*/
{ int b,c;
…… } /*a,b,c作用域:仅限于函数 f1()中 */
int f2(int x) /*函数 f2*/
{ int y,z;
…… } /*x,y,z作用域:仅限于函数 f2()中 */
main()
{ int m,n;
…… } /*m,n作用域:仅限于函数 main()中 */
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.全局变量返回 本节 目录全局变量也称为外部变量,它是在函数外部定义的变量。 它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局变量说明。 只有在函数内经过说明的全局变量才能使用。全局变量的说明符为
extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。 例如:
int a,b; /*外部变量 */
void f1() /*函数 f1*/
{
……
}
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
float x,y; /*外部变量 */
int fz() /*函数 fz*/
{
……
}
main() /*主函数 */
{
……
} /*全局变量 x,y作用域 全局变量 a,b作用域 */
从上例可以看出 a,b,x,y 都是在函数外部定义的外部变量,都是全局变量。但 x,y 定义在函数 f1之后,而在 f1内又无对 x,y的说明,
所以它们在 f1内无效。 a,b定义在源程序最前面,因此在 f1,f2及
main内不加说明也可使用。
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【例 5.10】输入长方体的长宽高 l,w,h。求体积及三个面 x*y,x*z,y*z
的面积。
/*程序代码文件名,l5_10.cpp /
/*功能:求长方体体积及三个面 x*y,x*z,y*z的面积。 */
int s1,s2,s3;
int vs( int a,int b,int c)
{
int v;
v=a*b*c;
s1=a*b;
s2=b*c;
s3=a*c;
return v;
}
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
main()
{
int v,l,w,h;
printf("\ninput length,width and height,");
scanf("%d%d%d",&l,&w,&h);
v=vs(l,w,h);
printf("v=%d s1=%d s2=%d s3=%d\n",v,s1,s2,s3);
}
程序运行结果如下:
input length,width and height:4 5 6 <CR>
v=120 s1=20 s2=30 s3=24
5.6.2全局变量和局部变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录程序说明,
本程序中定义了三个外部变量 s1,s2,s3,用来存放三个面积,其作用域为整个程序。函数 vs用来求正方体体积和三个面积,函数的返回值为体积 v。由主函数完成长宽高的输入及结果输出。
由于C语言规定函数返回值只有一个,当需要增加函数的返回数据时,用外部变量是一种很好的方式。本例中,如不使用外部变量,在主函数中就不可能取得 v,s1,s2,s3四个值。而采用了外部变量,在函数 vs中求得的 s1,s2,s3值在 main 中仍然有效。因此外部变量是实现函数之间数据通讯的有效手段。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.7.2函数的存储类型
5.7.1变量的存储类型
5.7变量及函数的存储类型
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.自动变量返回 本节 目录自动变量的类型说明符为 auto
这种存储类型是C语言程序中使用最广泛的一种类型。
C语言规定,函数内凡未加存储类型说明的变量均视为自动变量,
也就是说自动变量可省去说明符 auto。 在前面各章的程序中所定义的变量凡未加存储类型说明符的都是自动变量。例如:
{ int a,b,k;
char c;
……
}等价于:
{ auto int a,b,k;
auto char c;
……
}
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录自动变量具有以下特点:
(1) 自动变量的作用域仅限于定义该变量的个体内。
(2) 自动变量属于动态存储方式,只有在使用它,即定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。
(3) 由于自动变量的作用域和生存期都局限于定义它的个体内 ( 函数或复合语句内 ),因此不同的个体中允许使用同名的变量而不会混淆。
(4) 对构造类型的自动变量如数组等,不可作初始化赋值。
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.外部变量返回 本节 目录外部变量的类型说明符为 extern。
在前面介绍全局变量时已介绍过外部变量。这里再补充说明外部变量的几个特点:
(1) 外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。
( 2)当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其它的源文件中也有效。
5.7.1变量的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3.静态变量返回 本节 目录静态变量的类型说明符是 static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,
例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。 对于自动变量,前面已经介绍它属于动态存储方式。
但是也可以用 static定义它为静态自动变量,或称静态局部变量。
4.寄存器变量寄存器变量的说明符是 register 。这种变量存放在 CPU的寄存器中,
使用时,不需要访问内存,而直接从寄存器中读写,这样可提高效率。
5.7.2 函数的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,内部函数(又称静态函数)
返回 本节 目录如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
定义一个内部函数,只需在函数类型前再加一个,static”关键字即可,如下所示:
static 函数类型 函数名 (函数参数表 )
{……}
关键字,static”,译成中文就是“静态的”,所以内部函数又称静态函数。但此处,static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
5.7.2 函数的存储类型
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.外部函数返回 本节 目录外部函数的定义:在定义函数时,如果没有加关键字,static”,冠以关键字,extern”,表示此函数是外部函数:
[extern] 函数类型 函数名 (函数参数表 )
{……}
调用外部函数时,需要对其进行说明:
[extern] 函数类型 函数名 (参数类型表 )[,函数名 2(参数类型表
2)……] ;
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本章 目录
5.8.2 文件包含
5.8.1 宏定义
5.8 编译预处理
5.8.3 条件编译
5.8.1 宏定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1.无参宏定义返回 本节 目录无参宏的宏名后不带参数。
其定义的一般形式为,#define 标识符 字符串其中的,#”表示这是一条预处理命令。凡是以,#”开头的均为预处理命令。
,define”为宏定义命令。,标识符”为所定义的宏名。“字符串”
可以是常数、表达式、格式串等。
在前面介绍过的符号常量的定义就是一种无参宏定义。 此外,常对程序中反复使用的表达式进行宏定义。
例如,# define M (y*y+3*y) 定义 M 为表达式 (y*y+3*y)。在编写源程序时,所有的 (y*y+3*y)都可由 M代替,而对源程序作编译时,将先由预处理程序进行宏代换,即用 (y*y+3*y)表达式去置换所有的宏名 M,然后再进行编译。
5.8.1 宏定义
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2.带参宏定义返回 本节 目录
C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,
而且要用实参去代换形参。
带参宏定义的一般形式为,#define 宏名 (形参表 ) 字符串在字符串中含有各个形参。
带参宏调用的一般形式为,宏名 (实参表 );
例如:
#define M(y) y*y+3*y /*宏定义 */
,
k=M(5); /*宏调用 */
,
在宏调用时,用实参 5去代替形参 y,经预处理宏展开后的语句为,k=5*5+3*5
5.8.2 文件包含
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录文件包含命令行的一般形式为,#include"文件名 "在前面我们已多次用此命令包含过库函数的头文件。例如:
#include"stdio.h"
#include"math.h"
文件包含命令的功能,是把指定的文件插入该命令行位置取代该命令行,
从而把指定的文件和当前的源程序文件连成一个源文件。
对文件包含命令还要说明以下几点:
(1),包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找 (包含目录是由用户在设置环境时设置的 ),而不在源文件目录去查找; 使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。
用户编程时可根据自己文件所在的目录来选择某一种命令形式。
(2),一个 include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个 include命令。
(3),文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
1,第一种形式:
返回 本节 目录
#ifdef 标识符程序段 1
#else
程序段 2
#endif
它的功能是,如果标识符已被 #define命令定义过则对程序段 1进行编译;否则对程序段 2进行编译。 如果没有程序段 2(它为空 ),本格式中的 #else可以没有,即可以写为:
#ifdef 标识符程序段 #endif
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
2,第 二 种形式:
返回 本节 目录
#ifndef 标识符程序段 1
#else
程序段 2
#endif
与第一种形式的区别是将,ifdef”改为,ifndef”。
它的功能是:如果标识符未被 #define命令定义过则对程序段 1进行编译,否则对程序段 2进行编译。这与第一种形式的功能正相反。
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
3,第三种形式:
返回 本节 目录
#if 常量表达式程序段 1
#else
程序段 2
#endif
它的功能是,如常量表达式的值为真 (非 0),则对程序段 1 进行编译,否则对程序段 2进行编译。因此可以使程序在不同条件下,完成不同的功能
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
【例 5.11】 计算圆面积
/*程序代码文件名,l5_11.cpp /
#define R 1
main()
{
float c,r,s;
printf ("input a number,");
scanf("%f",&c);
#if R
r=3.14159*c*c;
printf("area of round is,%f\n",r);
#else
s=c*c;
5.8.3 条件编译
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境
)
返回 本节 目录
printf("area of square is,%f\n",s);
#endif
}
运行的结果如下,
input a number:10<CR>
area of round is:314.158997
程序说明,本例中采用了第三种形式的条件编译。在程序第一行宏定义中,定义 R为 1,因此在条件编译时,常量表达式的值为真,故计算并输出圆面积。
上面介绍的条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段 1或程序段 2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。