第七章 函数及变量存贮类型
第七章 函数及变量存贮类型
7.1 函数基础与 C程序结构
7.2 函数的定义和声明
7.3 函数的调用
7.4 函数的嵌套与递归
7.5 变量的存贮类别
第七章 函数及变量存贮类型
7.1 函数基础与 C程序结构
7.1.1 C程序的结构化设计思想
图 7.1 C程序结构示意图
C 程序
源程序2源程序1
m a i n ( )数据定义
源程序n
自定义函数
说明部分 执行部分
?
第七章 函数及变量存贮类型
7.1.2 函数概述
在 C程序设计中, 函数是独立的 C程序模块, 它完成一
个特定任务并可选择是否将一个值返回调用程序 。 在 C语言
中, 子程序被称为函数, 它相应于其它高级语言中的过程
( 无返回值的子程序 ) 和函数 ( 通过函数名返回一个值的
子程序 ) 。 一个 C程序一般由多个函数组成, 其中必须有一
个且仅有一个名为 main的主函数, 其余为被 main函数或其
它函数调用的函数, 无论 main函数位于程序中什么位置,
C程序总是从 main函数开始执行 。
第七章 函数及变量存贮类型
main函数可调用其它函数来实现所需的功能 。 被 main函
数调用的函数分为两类:一类是由系统提供的标准库函数,
例如, 标准输入输出函数 ( scanf,printf,getche,putchar,…),
数学计算函数 ( sin,cos,fabs,sqrt,…), 数据格式转
换函数 ( atoi,atof,sscanf,sprintf,…), 字符串处理函数
( strlen,strcpy,strcmp,…) 和文件读写函数 ( fread,
fwrite,fopen,…) 等 。 这类函数可以由用户程序直接调用;
另一类是用户在自己的程序中定义的函数, 即需要由用户自
己编写的函数 。
第七章 函数及变量存贮类型
例 7.1 用户自定义函数 —— 求数的平方。
# include <stdio.h>
long square(long); /* 函数声明 */
void main()
{ long in -num,result;
printf(" Input an integer," );
scanf(" %ld",&in -num);
result=square (in -num); /* 函数调用 */
printf("\ nThe square number of %ld is %ld",in -num,result);
}
第七章 函数及变量存贮类型
long square (long x) /* 函数定义 */
{ long x -square; /* 说明部分 */
x -square=x*x; /* 执行部分 */
return x -square;
}
Input an integer,100 (输入 )
The square number of 100 is 10000 (输出 )
第七章 函数及变量存贮类型
7.2 函数的定义和声明
7.2.1 函数的定义
例 7.2 计算 x的 n次方,x=2,-3;( n=1,2,… 9)。
# include<stdio.h>
int main(void) / * 测试 power函数 *
{ int i;
double power(int,int); /* 函数声明 */
for(i=1; i<10; i++)
printf(" power(2,%d)=%8.4f,power(-3,%d)=%11.4f\n",
第七章 函数及变量存贮类型
i,power(2,i),i,power(-3,i));
return 0;
}
double power(int x,int n) /* 函数首部 */
{ int i; /* 说明部分 */
double p;
p=1; /* 执行部分 */
for(i=1; i<=n; i++)
p*=x;
return(p); /* 返回 p值 */
}
第七章 函数及变量存贮类型
输出,
power( 2,1) = 2,0000,power( -3,1) = -3,0000
power( 2,2) = 4,0000,power( -3,2) = 9,0000
power( 2,3) = 8,0000,power( -3,3) = -27,0000
power( 2,4) = 16,0000,power( -3,4) = 81,0000
power( 2,5) = 32,0000,power( -3,5) = -243,0000
power( 2,6) = 64,0000,power( -3,6) = 729,0000
power( 2,7) =128,0000,power( -3,7) = -2187,0000
power( 2,8) =256,0000,power( -3,8) = 6561,0000
power( 2,9) =512,0000,power( -3,9) =-19683,0000
第七章 函数及变量存贮类型
函数名 power是一个标识符, power函数具有 double类型的
返回值, 它有两个 int类型的参数 x和 n。 { } 括起来的部分是
函数体, 其中的说明部分, int i; double p;, 说明 i,p是在
power函数内部使用的局部变量 。 执行部分的, return( p) ;,
语句将表达式 p的值返回给 main函数的调用处, p的值就是
power函数的返回值 ( 简称函数值 ) 。
函数定义的一般形式为,
存贮类型标识符 类型标识符 函数名 ( 形式参数表列及类
型说明 )
{
}
第七章 函数及变量存贮类型
1)
存贮类型标识符说明函数的存贮类型, 它规定了函数
可被调用的范围 。 可用于函数的存贮类型标识符有 static和
extern,指定为 static的函数为静态函数, 静态函数局部于它
所在的文件, 即只能由和它在同一文件中定义的函数调用;
不指定存贮类型标识符时为缺省的存贮类型 extern,缺省或
指定为 extern存贮类型的函数是外部函数, 例如, 例 7.2中的
power函数是外部函数 。 外部函数可以被任何函数调用 。
第七章 函数及变量存贮类型
2)
C程序中定义的函数可以什么也不返回而只完成某项工作 。
无返回值的函数, 类型标识符为 void,又称为, 空类型函数,,
即此函数不向主调函数返回值, 主调函数也禁止使用此函数的
返回值 。
C程序中定义的函数也可以返回一个值, 这时, 类型标识
符说明函数返回值的数据类型 ( 常简称为, 函数值的类型, 或
,函数的类型, ), 例如, 例 7.2中的 power函数是一个 double类
型函数, main是 int类型函数 。 函数的类型可以为任何基本类型,
结构体和共用体类型 。 还可以定义返回值为指针的函数, 但不
能定义返回数组的函数 。 int型函数定义时可以省略类型标识符
int,因为 int是有返回值函数的缺省类型 ( 提倡明确指出 int) 。
第七章 函数及变量存贮类型
3)
函数名是一个标识符, 一个程序中除主函数 main外,
其余函数的名字可以任意取, 最好取有助于记忆的名字 。
考虑到与外部联接的需要, 函数名一般不要超过 6个字符长,
如 max(),power( )和 factor()等 。 外部函数的名字是作用于整
个程序, 因而外部函数相互之间不能同名 。 静态函数可以
和外部函数同名, 但同一文件中的函数不能同名 。
第七章 函数及变量存贮类型
4)
函数定义中的参数表说明函数参数的名称, 类型和数目 。
参数表由零个或多个参数说明组成, 如果函数没有参数, 可只
写一对括号 (此为函数标志, 不可省略 ),但最好将参数表指定
为 void。 有多个参数时, 多个参数之间用逗号隔开 。 函数定义
中的参数表习惯上称为形参表 。
类型标识符
每个类型标识符对应于一个形参名, 当有多个形参时, 相互
间用逗号隔开 。
第七章 函数及变量存贮类型
5) 函数体和函数返回值
函数定义中最外层 { } 括起来的部分称为函数体, 函数
体由说明部分和执行部分组成 。 说明部分是局部说明, 执行
部分是可执行语句的序列, 完成本函数要完成的具体任务 。
局部说明中说明的变量和函数其有效范围局限于该函数内部,
同形参一样, 不能由其它任何函数存取 ( 或调用 ) 。
函数体语法上是一个复合语句, 它可以没有说明部分而
只有执行部分, 也可以两者都没有 。 因此最简单的合法函数
是形参表为空 ( void) 且函数体也为空的函数 ( 称为哑函数 ),
例如,void dummy( void) { }
第七章 函数及变量存贮类型
7.2.2 函数的声明
函数声明的一般形式,
存贮类型标识符 类型标识符 函数名 (形参表 );
外部函数声明时可指定 extern或存贮类型标识符缺省,
静态函数声明时必须指定 static;参数表可以只列出参数的类
型名而不需给出参数名 。 例如,
double power(int,int);
和 double power(int x,int n);
是等价的 。 power函数是 double类型, 它有两个 int参数 。
对于无参数表的函数, 声明时参数表应指定为 void。
第七章 函数及变量存贮类型
7.3 函 数 的 调 用
7.3.1 函数调用的方式和条件
函数调用的一般形式为,
函数名 ( 实参 1,实参 2,…,实参 n)
( ) 部分称为实参表, 实参可以是常量, 变量或表达
式, 有多个实参时, 相互间用逗号隔开 。 实参和形参应在
数目, 次序和类型上一致 。 对于无参数的函数, 调用时实
参表为空, 但 ( ) 不能省 。
第七章 函数及变量存贮类型
(1) getch( ) ; getch函数调用作为语句出现 。
(2) c=getchar(); getchar函数调用作表达式出现 ( 赋值表
达式的右操作数 ) 。
(3) while( putchar( getche()) ! =′? ′) ;
getche函数调用作为 putchar函数调用的实参 ( 表达式 )
出现, putchar函数调用作为关系表达式的左操作数 ( 表达式 )
出现 。
(4) while((c=getch())! =′?′) putchar( c) ;
putchar函数调用作为 while语句的循环体(语句)出现。
第七章 函数及变量存贮类型
函数调用的一般过程为,
(1) 主调函数在执行过程中, 一旦遇到函数调用, 系统
首先计算实参表达式的值并为每个形参分配存贮单元, 然后
把实参值复制到 ( 送到或存入 ) 对应形参的存贮单元中 。 实
参与形参按位置一一对应 。
(2) 将控制转移到被调用的函数, 执行其函数体内的语
句 。
(3) 当执行 return语句或到达函数体末尾时, 控制返回到
调用处, 如果有返回值, 同时回送一个值 。 然后从函数调用
点继续执行主调函数后面的操作 。
第七章 函数及变量存贮类型
除了正确地编写函数的定义及调用语句, 要想成功地
调用某个函数还必须满足下列四个条件之一,
(1) 被调用函数的定义出现在主调函数的定义之前 。
(2) 在主调函数中或主调函数之前的外部对被调用函数
进行声明 。
(3) 被调用函数的返回值为 int型 。
(4) 被调用函数为标准函数时,在函数调用前已包含了
相应的头文件。
第七章 函数及变量存贮类型
7.3.2 形参与实参的数值传递
例 7.3 形参与实参的数值传递。
void swap(int x,int y)
{ int z;
z=x; x=y; y=z;
}
main()
{ int a,b;
a=10; b=20;
swap(a,b);
printf(" a=%d\tb=%d\n",a,b);
}
运行结果,
a=10 b=20
第七章 函数及变量存贮类型
10 20ba
10 20yx
10 20ba
20 10yx
( a ) ( b )
图 7.2
第七章 函数及变量存贮类型
例 7.4 参数的求值顺序。
void main(void)
{ int x=0;
printf(" x=%d\n",x);
printf(" x++=%d x++=%d\n",x++,x++);
printf(" x=%d\n",x);
}
执行时输出,
x=0
x++=1 x++=0
x=2
第七章 函数及变量存贮类型
7.3.3 函数的返回值
例 7.5 函数的返回值。
max(float x,float y)
{ if(x>=y) return(x);
else return(y);
}
main()
{ float a,b,c;
scanf(" %f%f",&a,&b);
c=max(a,b);
printf(" max=%5.2f\n",c);
}
运行情况如下,
2.5 5.6
max= 5.00
第七章 函数及变量存贮类型
7.4 函数的嵌套与递归
7.4.1 函数的嵌套调用
例 7.6 输入三个数, 计算以它们作为两个底的半径和高
所形成的圆台的体积 。
分析,已知圆台的上下底的半径,可用下式计算圆台的体积
)(
3
1
2211 SSSShV ?????
第七章 函数及变量存贮类型
程序如下,
# include <stdio.h>
# include <math.h>
# define PI 3.1416
float area(float r)
{ return(PI*r*r);
}
float volume(float r1,float r2,float h)
{ float v;
v=h*(area(r1)+area(r2)+sqrt(area(r1)*area(r2)))/3.0;
return(v);
}
第七章 函数及变量存贮类型
main()
{ float r1,r2,h;
printf(" Please input r1 r2 h,\n" );
scanf(" %f%f%f",&r1,&r2,&h);
printf(" The volume is %f\n",volume(r1,r2,h));
}
Please input r1 r2 h,
2.5 6.8 3.3
The volume is 240.140762
第七章 函数及变量存贮类型
7.4.2 函数的递归及条件
递归是一种特殊的解决问题的方法, 要用递归解决
问题, 应满足两个条件,
(1) 函数直接或间接地调用它本身;
(2) 应有使递归结束的条件。
第七章 函数及变量存贮类型
例 7.7 用函数递归方法以字符串形式输出一个整数。
# include<stdio.h>
void printd(int n)
{ if(n<0)
{putchar(′-′);
n=-n;
}
if(n/10) /* n/10==0时,递归结束 */
printd(n/10); /* 递归调用 */
putchar(n%10+′0′); /* 以字符输出 */
}
void main()
{ int number;
scanf(" %d",&number);
printd(number);
}
第七章 函数及变量存贮类型
7.5 变量的存贮类别
7.5.1 变量的作用域和生存期
例 7.8 变量的作用域。
# include <stdio.h>
int x= 999; /* 定义全局变量 x */
void print -value(void);
void main()
{ printf(" %d\n",x);
print -value();
}
void print -value(void)
{ printf(" %d\n",x);
}
输出,999
999
第七章 函数及变量存贮类型
例 7.9 变量的作用域。
# include <stdio.h>
void print -value(void);
void main()
{ int x=999; /* 定义局部变量 x */
printf(" %d\n",x);
print -value();
}
void print -value(void)
{ printf(" %d\n",x);
}
第七章 函数及变量存贮类型
7.5.2 动态存贮和静态存贮
内存中供用户使用的存贮空间可分为程序区, 动态存贮
区和静态存贮区 。 程序区用来存放程序代码, 动态存贮区和
静态存贮区用来存放数据, 即数据与处理数据的程序是分离
的, 这是面向过程的程序设计方法的特点 。
动态存贮和静态存贮是指 C对数据存贮的两种方式 。 动
态存贮是指存贮一些数据的存贮单元可在程序运行的不同时
间分配给不同的数据, 而静态存贮是指存贮单元在程序运行
的整个过程中固定地分配给某些数据 。
第七章 函数及变量存贮类型
7.5.3 局部变量
局部变量又称内部变量,是在一个函数内定义,其作用
域限制在所定义的函数中。
例 7.10 局部变量与全局变量同名。
int a=1,b=2; /* 定义全局变量 a,b */
max(int a,int b) /* 子函数中的局部变量 a,b */
{int c;
c=a>b?a,b;
return(c);
}
main()
{int a=8; /* 定义局部变量 a */
printf(" %d",max(a,b));
}
运行结果,
8
第七章 函数及变量存贮类型
7.5.4 局部静态变量的使用
例 7.11 静态局部变量的使用。
void f()
{ int a,b=3;
static int c,d=5;
a=3; c=5;
a++; b++; c++; d++;
printf(" %d \t %d \t %d \t %d\n",a,b,c,d);
}
main()
{ f(); f();
}
运行结果,
4 4 6 6
4 4 6 7
第七章 函数及变量存贮类型
例 7.12 打印 1到 5的阶乘。
fac(int n)
{ static int f=1;
f*=n;
return(f);
}
main()
{ int i;
for(i=1; i<=5; i++)
printf(" %d!=%d\n",i,fac(i));
}
第七章 函数及变量存贮类型
运行结果,
1! =1
2! =2
3! =6
4! =24
5! =120
第七章 函数及变量存贮类型
7.5.5 全局变量
全局变量 ( 也称外部变量 ) 是在所有函数, 包括 main函
数之外定义的 。 全局变量是存放在静态存贮区中的, 它的作
用域是从全局变量定义之后直到该源文件结束的所有函数;
通过用 extern作引用说明, 全局变量的作用域可以扩大到整
个程序的所有文件 。 在定义全局变量时可以使用 static存贮类
型标识符, 它与普通全局变量的区别在于变量的作用域 。 普
通全局变量不仅对文件中的所有函数都是可见的, 而且能被
其它文件中的函数所用;而 static型的全局变量仅对其所在文
件中定义处之后的函数是可见的, 不能被其它文件使用 。 这
种差别适合于程序源代码包含在两个或多个文件中的情况 。
第七章 函数及变量存贮类型
全局变量初始化是在全局变量定义时进行的, 且其初
始化仅执行一次, 若无显式初始化, 则由系统自动初始
化为与变量类型相同的 0初值,
整型变量初始化为整数 0
浮点型变量初始化为浮点数 0.0
字符型变量初始化为空字符 ′\ 0′
在有显式初始化的情况下, 初值必须是常量表达式 。 全
局变量存放在静态存贮区中, 全局变量在程序执行之前
分配存贮单元, 在程序运行结束后才被收回 。
第七章 函数及变量存贮类型
例 7.13 输入以秒为单位的一个时间值, 将其转化成
,时,分:秒, 的形式输出 。 将转换工作定义成函数 。
# include<stdio.h>
int hh,mm,ss;
void convertime(long seconds)
{ hh=seconds/3600;
mm=(seconds-hh*3600L)/60;
ss=seconds-hh*3600L-mm*60;
}
void main(void)
{ long seconds;
第七章 函数及变量存贮类型
printf(" hh=%d,mm=%d,ss=%d\n",hh,mm,ss);
printf(" input a time in second," );
scanf(" %ld",&seconds);
convertime(seconds);
printf(" %2d,%2d,%2d\n",hh,mm,ss);
}
执行时输出,
hh= 0,mm= 0,ss= 0
input a time in second,41574 (输入 )
11,32,54 (输出 )
第七章 函数及变量存贮类型
7.5.6 寄存器变量
例 7.14 计算 s=x1+ x2+ x3+ …+ xn,x和 n由终端输入。
# include<stdio.h>
long sum(register int x,int n)
{ long s;
int i;
register int t;
t=s=x;
for(i=2; i<= n; i++)
{t*=x;
s+=t;
}
第七章 函数及变量存贮类型
return(s);
main()
{ int x,n;
printf(" Input x,n:" );
scanf(" %d %d",&x,&n);
printf(" s=%ld\n",sum(x,n));
}
执行时输出,
Input x,n,4 5
S=1364
第七章 函数及变量存贮类型
7.1 函数基础与 C程序结构
7.2 函数的定义和声明
7.3 函数的调用
7.4 函数的嵌套与递归
7.5 变量的存贮类别
第七章 函数及变量存贮类型
7.1 函数基础与 C程序结构
7.1.1 C程序的结构化设计思想
图 7.1 C程序结构示意图
C 程序
源程序2源程序1
m a i n ( )数据定义
源程序n
自定义函数
说明部分 执行部分
?
第七章 函数及变量存贮类型
7.1.2 函数概述
在 C程序设计中, 函数是独立的 C程序模块, 它完成一
个特定任务并可选择是否将一个值返回调用程序 。 在 C语言
中, 子程序被称为函数, 它相应于其它高级语言中的过程
( 无返回值的子程序 ) 和函数 ( 通过函数名返回一个值的
子程序 ) 。 一个 C程序一般由多个函数组成, 其中必须有一
个且仅有一个名为 main的主函数, 其余为被 main函数或其
它函数调用的函数, 无论 main函数位于程序中什么位置,
C程序总是从 main函数开始执行 。
第七章 函数及变量存贮类型
main函数可调用其它函数来实现所需的功能 。 被 main函
数调用的函数分为两类:一类是由系统提供的标准库函数,
例如, 标准输入输出函数 ( scanf,printf,getche,putchar,…),
数学计算函数 ( sin,cos,fabs,sqrt,…), 数据格式转
换函数 ( atoi,atof,sscanf,sprintf,…), 字符串处理函数
( strlen,strcpy,strcmp,…) 和文件读写函数 ( fread,
fwrite,fopen,…) 等 。 这类函数可以由用户程序直接调用;
另一类是用户在自己的程序中定义的函数, 即需要由用户自
己编写的函数 。
第七章 函数及变量存贮类型
例 7.1 用户自定义函数 —— 求数的平方。
# include <stdio.h>
long square(long); /* 函数声明 */
void main()
{ long in -num,result;
printf(" Input an integer," );
scanf(" %ld",&in -num);
result=square (in -num); /* 函数调用 */
printf("\ nThe square number of %ld is %ld",in -num,result);
}
第七章 函数及变量存贮类型
long square (long x) /* 函数定义 */
{ long x -square; /* 说明部分 */
x -square=x*x; /* 执行部分 */
return x -square;
}
Input an integer,100 (输入 )
The square number of 100 is 10000 (输出 )
第七章 函数及变量存贮类型
7.2 函数的定义和声明
7.2.1 函数的定义
例 7.2 计算 x的 n次方,x=2,-3;( n=1,2,… 9)。
# include<stdio.h>
int main(void) / * 测试 power函数 *
{ int i;
double power(int,int); /* 函数声明 */
for(i=1; i<10; i++)
printf(" power(2,%d)=%8.4f,power(-3,%d)=%11.4f\n",
第七章 函数及变量存贮类型
i,power(2,i),i,power(-3,i));
return 0;
}
double power(int x,int n) /* 函数首部 */
{ int i; /* 说明部分 */
double p;
p=1; /* 执行部分 */
for(i=1; i<=n; i++)
p*=x;
return(p); /* 返回 p值 */
}
第七章 函数及变量存贮类型
输出,
power( 2,1) = 2,0000,power( -3,1) = -3,0000
power( 2,2) = 4,0000,power( -3,2) = 9,0000
power( 2,3) = 8,0000,power( -3,3) = -27,0000
power( 2,4) = 16,0000,power( -3,4) = 81,0000
power( 2,5) = 32,0000,power( -3,5) = -243,0000
power( 2,6) = 64,0000,power( -3,6) = 729,0000
power( 2,7) =128,0000,power( -3,7) = -2187,0000
power( 2,8) =256,0000,power( -3,8) = 6561,0000
power( 2,9) =512,0000,power( -3,9) =-19683,0000
第七章 函数及变量存贮类型
函数名 power是一个标识符, power函数具有 double类型的
返回值, 它有两个 int类型的参数 x和 n。 { } 括起来的部分是
函数体, 其中的说明部分, int i; double p;, 说明 i,p是在
power函数内部使用的局部变量 。 执行部分的, return( p) ;,
语句将表达式 p的值返回给 main函数的调用处, p的值就是
power函数的返回值 ( 简称函数值 ) 。
函数定义的一般形式为,
存贮类型标识符 类型标识符 函数名 ( 形式参数表列及类
型说明 )
{
}
第七章 函数及变量存贮类型
1)
存贮类型标识符说明函数的存贮类型, 它规定了函数
可被调用的范围 。 可用于函数的存贮类型标识符有 static和
extern,指定为 static的函数为静态函数, 静态函数局部于它
所在的文件, 即只能由和它在同一文件中定义的函数调用;
不指定存贮类型标识符时为缺省的存贮类型 extern,缺省或
指定为 extern存贮类型的函数是外部函数, 例如, 例 7.2中的
power函数是外部函数 。 外部函数可以被任何函数调用 。
第七章 函数及变量存贮类型
2)
C程序中定义的函数可以什么也不返回而只完成某项工作 。
无返回值的函数, 类型标识符为 void,又称为, 空类型函数,,
即此函数不向主调函数返回值, 主调函数也禁止使用此函数的
返回值 。
C程序中定义的函数也可以返回一个值, 这时, 类型标识
符说明函数返回值的数据类型 ( 常简称为, 函数值的类型, 或
,函数的类型, ), 例如, 例 7.2中的 power函数是一个 double类
型函数, main是 int类型函数 。 函数的类型可以为任何基本类型,
结构体和共用体类型 。 还可以定义返回值为指针的函数, 但不
能定义返回数组的函数 。 int型函数定义时可以省略类型标识符
int,因为 int是有返回值函数的缺省类型 ( 提倡明确指出 int) 。
第七章 函数及变量存贮类型
3)
函数名是一个标识符, 一个程序中除主函数 main外,
其余函数的名字可以任意取, 最好取有助于记忆的名字 。
考虑到与外部联接的需要, 函数名一般不要超过 6个字符长,
如 max(),power( )和 factor()等 。 外部函数的名字是作用于整
个程序, 因而外部函数相互之间不能同名 。 静态函数可以
和外部函数同名, 但同一文件中的函数不能同名 。
第七章 函数及变量存贮类型
4)
函数定义中的参数表说明函数参数的名称, 类型和数目 。
参数表由零个或多个参数说明组成, 如果函数没有参数, 可只
写一对括号 (此为函数标志, 不可省略 ),但最好将参数表指定
为 void。 有多个参数时, 多个参数之间用逗号隔开 。 函数定义
中的参数表习惯上称为形参表 。
类型标识符
每个类型标识符对应于一个形参名, 当有多个形参时, 相互
间用逗号隔开 。
第七章 函数及变量存贮类型
5) 函数体和函数返回值
函数定义中最外层 { } 括起来的部分称为函数体, 函数
体由说明部分和执行部分组成 。 说明部分是局部说明, 执行
部分是可执行语句的序列, 完成本函数要完成的具体任务 。
局部说明中说明的变量和函数其有效范围局限于该函数内部,
同形参一样, 不能由其它任何函数存取 ( 或调用 ) 。
函数体语法上是一个复合语句, 它可以没有说明部分而
只有执行部分, 也可以两者都没有 。 因此最简单的合法函数
是形参表为空 ( void) 且函数体也为空的函数 ( 称为哑函数 ),
例如,void dummy( void) { }
第七章 函数及变量存贮类型
7.2.2 函数的声明
函数声明的一般形式,
存贮类型标识符 类型标识符 函数名 (形参表 );
外部函数声明时可指定 extern或存贮类型标识符缺省,
静态函数声明时必须指定 static;参数表可以只列出参数的类
型名而不需给出参数名 。 例如,
double power(int,int);
和 double power(int x,int n);
是等价的 。 power函数是 double类型, 它有两个 int参数 。
对于无参数表的函数, 声明时参数表应指定为 void。
第七章 函数及变量存贮类型
7.3 函 数 的 调 用
7.3.1 函数调用的方式和条件
函数调用的一般形式为,
函数名 ( 实参 1,实参 2,…,实参 n)
( ) 部分称为实参表, 实参可以是常量, 变量或表达
式, 有多个实参时, 相互间用逗号隔开 。 实参和形参应在
数目, 次序和类型上一致 。 对于无参数的函数, 调用时实
参表为空, 但 ( ) 不能省 。
第七章 函数及变量存贮类型
(1) getch( ) ; getch函数调用作为语句出现 。
(2) c=getchar(); getchar函数调用作表达式出现 ( 赋值表
达式的右操作数 ) 。
(3) while( putchar( getche()) ! =′? ′) ;
getche函数调用作为 putchar函数调用的实参 ( 表达式 )
出现, putchar函数调用作为关系表达式的左操作数 ( 表达式 )
出现 。
(4) while((c=getch())! =′?′) putchar( c) ;
putchar函数调用作为 while语句的循环体(语句)出现。
第七章 函数及变量存贮类型
函数调用的一般过程为,
(1) 主调函数在执行过程中, 一旦遇到函数调用, 系统
首先计算实参表达式的值并为每个形参分配存贮单元, 然后
把实参值复制到 ( 送到或存入 ) 对应形参的存贮单元中 。 实
参与形参按位置一一对应 。
(2) 将控制转移到被调用的函数, 执行其函数体内的语
句 。
(3) 当执行 return语句或到达函数体末尾时, 控制返回到
调用处, 如果有返回值, 同时回送一个值 。 然后从函数调用
点继续执行主调函数后面的操作 。
第七章 函数及变量存贮类型
除了正确地编写函数的定义及调用语句, 要想成功地
调用某个函数还必须满足下列四个条件之一,
(1) 被调用函数的定义出现在主调函数的定义之前 。
(2) 在主调函数中或主调函数之前的外部对被调用函数
进行声明 。
(3) 被调用函数的返回值为 int型 。
(4) 被调用函数为标准函数时,在函数调用前已包含了
相应的头文件。
第七章 函数及变量存贮类型
7.3.2 形参与实参的数值传递
例 7.3 形参与实参的数值传递。
void swap(int x,int y)
{ int z;
z=x; x=y; y=z;
}
main()
{ int a,b;
a=10; b=20;
swap(a,b);
printf(" a=%d\tb=%d\n",a,b);
}
运行结果,
a=10 b=20
第七章 函数及变量存贮类型
10 20ba
10 20yx
10 20ba
20 10yx
( a ) ( b )
图 7.2
第七章 函数及变量存贮类型
例 7.4 参数的求值顺序。
void main(void)
{ int x=0;
printf(" x=%d\n",x);
printf(" x++=%d x++=%d\n",x++,x++);
printf(" x=%d\n",x);
}
执行时输出,
x=0
x++=1 x++=0
x=2
第七章 函数及变量存贮类型
7.3.3 函数的返回值
例 7.5 函数的返回值。
max(float x,float y)
{ if(x>=y) return(x);
else return(y);
}
main()
{ float a,b,c;
scanf(" %f%f",&a,&b);
c=max(a,b);
printf(" max=%5.2f\n",c);
}
运行情况如下,
2.5 5.6
max= 5.00
第七章 函数及变量存贮类型
7.4 函数的嵌套与递归
7.4.1 函数的嵌套调用
例 7.6 输入三个数, 计算以它们作为两个底的半径和高
所形成的圆台的体积 。
分析,已知圆台的上下底的半径,可用下式计算圆台的体积
)(
3
1
2211 SSSShV ?????
第七章 函数及变量存贮类型
程序如下,
# include <stdio.h>
# include <math.h>
# define PI 3.1416
float area(float r)
{ return(PI*r*r);
}
float volume(float r1,float r2,float h)
{ float v;
v=h*(area(r1)+area(r2)+sqrt(area(r1)*area(r2)))/3.0;
return(v);
}
第七章 函数及变量存贮类型
main()
{ float r1,r2,h;
printf(" Please input r1 r2 h,\n" );
scanf(" %f%f%f",&r1,&r2,&h);
printf(" The volume is %f\n",volume(r1,r2,h));
}
Please input r1 r2 h,
2.5 6.8 3.3
The volume is 240.140762
第七章 函数及变量存贮类型
7.4.2 函数的递归及条件
递归是一种特殊的解决问题的方法, 要用递归解决
问题, 应满足两个条件,
(1) 函数直接或间接地调用它本身;
(2) 应有使递归结束的条件。
第七章 函数及变量存贮类型
例 7.7 用函数递归方法以字符串形式输出一个整数。
# include<stdio.h>
void printd(int n)
{ if(n<0)
{putchar(′-′);
n=-n;
}
if(n/10) /* n/10==0时,递归结束 */
printd(n/10); /* 递归调用 */
putchar(n%10+′0′); /* 以字符输出 */
}
void main()
{ int number;
scanf(" %d",&number);
printd(number);
}
第七章 函数及变量存贮类型
7.5 变量的存贮类别
7.5.1 变量的作用域和生存期
例 7.8 变量的作用域。
# include <stdio.h>
int x= 999; /* 定义全局变量 x */
void print -value(void);
void main()
{ printf(" %d\n",x);
print -value();
}
void print -value(void)
{ printf(" %d\n",x);
}
输出,999
999
第七章 函数及变量存贮类型
例 7.9 变量的作用域。
# include <stdio.h>
void print -value(void);
void main()
{ int x=999; /* 定义局部变量 x */
printf(" %d\n",x);
print -value();
}
void print -value(void)
{ printf(" %d\n",x);
}
第七章 函数及变量存贮类型
7.5.2 动态存贮和静态存贮
内存中供用户使用的存贮空间可分为程序区, 动态存贮
区和静态存贮区 。 程序区用来存放程序代码, 动态存贮区和
静态存贮区用来存放数据, 即数据与处理数据的程序是分离
的, 这是面向过程的程序设计方法的特点 。
动态存贮和静态存贮是指 C对数据存贮的两种方式 。 动
态存贮是指存贮一些数据的存贮单元可在程序运行的不同时
间分配给不同的数据, 而静态存贮是指存贮单元在程序运行
的整个过程中固定地分配给某些数据 。
第七章 函数及变量存贮类型
7.5.3 局部变量
局部变量又称内部变量,是在一个函数内定义,其作用
域限制在所定义的函数中。
例 7.10 局部变量与全局变量同名。
int a=1,b=2; /* 定义全局变量 a,b */
max(int a,int b) /* 子函数中的局部变量 a,b */
{int c;
c=a>b?a,b;
return(c);
}
main()
{int a=8; /* 定义局部变量 a */
printf(" %d",max(a,b));
}
运行结果,
8
第七章 函数及变量存贮类型
7.5.4 局部静态变量的使用
例 7.11 静态局部变量的使用。
void f()
{ int a,b=3;
static int c,d=5;
a=3; c=5;
a++; b++; c++; d++;
printf(" %d \t %d \t %d \t %d\n",a,b,c,d);
}
main()
{ f(); f();
}
运行结果,
4 4 6 6
4 4 6 7
第七章 函数及变量存贮类型
例 7.12 打印 1到 5的阶乘。
fac(int n)
{ static int f=1;
f*=n;
return(f);
}
main()
{ int i;
for(i=1; i<=5; i++)
printf(" %d!=%d\n",i,fac(i));
}
第七章 函数及变量存贮类型
运行结果,
1! =1
2! =2
3! =6
4! =24
5! =120
第七章 函数及变量存贮类型
7.5.5 全局变量
全局变量 ( 也称外部变量 ) 是在所有函数, 包括 main函
数之外定义的 。 全局变量是存放在静态存贮区中的, 它的作
用域是从全局变量定义之后直到该源文件结束的所有函数;
通过用 extern作引用说明, 全局变量的作用域可以扩大到整
个程序的所有文件 。 在定义全局变量时可以使用 static存贮类
型标识符, 它与普通全局变量的区别在于变量的作用域 。 普
通全局变量不仅对文件中的所有函数都是可见的, 而且能被
其它文件中的函数所用;而 static型的全局变量仅对其所在文
件中定义处之后的函数是可见的, 不能被其它文件使用 。 这
种差别适合于程序源代码包含在两个或多个文件中的情况 。
第七章 函数及变量存贮类型
全局变量初始化是在全局变量定义时进行的, 且其初
始化仅执行一次, 若无显式初始化, 则由系统自动初始
化为与变量类型相同的 0初值,
整型变量初始化为整数 0
浮点型变量初始化为浮点数 0.0
字符型变量初始化为空字符 ′\ 0′
在有显式初始化的情况下, 初值必须是常量表达式 。 全
局变量存放在静态存贮区中, 全局变量在程序执行之前
分配存贮单元, 在程序运行结束后才被收回 。
第七章 函数及变量存贮类型
例 7.13 输入以秒为单位的一个时间值, 将其转化成
,时,分:秒, 的形式输出 。 将转换工作定义成函数 。
# include<stdio.h>
int hh,mm,ss;
void convertime(long seconds)
{ hh=seconds/3600;
mm=(seconds-hh*3600L)/60;
ss=seconds-hh*3600L-mm*60;
}
void main(void)
{ long seconds;
第七章 函数及变量存贮类型
printf(" hh=%d,mm=%d,ss=%d\n",hh,mm,ss);
printf(" input a time in second," );
scanf(" %ld",&seconds);
convertime(seconds);
printf(" %2d,%2d,%2d\n",hh,mm,ss);
}
执行时输出,
hh= 0,mm= 0,ss= 0
input a time in second,41574 (输入 )
11,32,54 (输出 )
第七章 函数及变量存贮类型
7.5.6 寄存器变量
例 7.14 计算 s=x1+ x2+ x3+ …+ xn,x和 n由终端输入。
# include<stdio.h>
long sum(register int x,int n)
{ long s;
int i;
register int t;
t=s=x;
for(i=2; i<= n; i++)
{t*=x;
s+=t;
}
第七章 函数及变量存贮类型
return(s);
main()
{ int x,n;
printf(" Input x,n:" );
scanf(" %d %d",&x,&n);
printf(" s=%ld\n",sum(x,n));
}
执行时输出,
Input x,n,4 5
S=1364