}
运行结果:max=5 5、函数的形参与实参
?、函数的参数分为形参和实参两种,作用是实现数据传送。
形参出现在函数定义中,只能在该函数体内使用。发生函数调用时,调用函数把实参的值复制1份,传送给被调用函数的形参,从而实现调用函数向被调用函数的数据传送。 练习7_3:实参对形参的数据传递。 /*实参对形参的数据传递。*/ void main() {
void s(int n); /*说明函数*/
int n=100; /*定义实参n,并初始化*/ s(n); /*调用函数*/
printf(\输出调用后实参的值,便于进行比较*/ }
void s(int n) {
int i;
printf(\输出改变前形参的值*/ for(i=n-1; i>=1; i--) n=n+i; /*改变形参的值*/
printf(\输出改变后形参的值*/ }
?、说明:
①实参可以是常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。
②形参变量只有在被调用时,才分配内存单元;调用结束时,即刻释放所分配的内存单元。 因此,形参只有在该函数内有效。调用结束,返回调用函数后,则不能再使用该形参变量。 ③实参对形参的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
④实参和形参占用不同的内存单元,即使同名也互不影响。 6、函数的嵌套调用和递归调用
?、函数的嵌套调用 指在执行被调用函数时,被调用函数又调用了其它函数。 如图所示:
?、函数的递归调用
- 21 -
函数的递归调用是指,一个函数在它的函数体内,直接或间接地调用它自身。
练习7_4 用递归函数解决猴子吃桃问题。问题描述如下:有一堆桃子不知其数,猴子每天吃前一天的一半多一个,到第十天只剩一个,试编程求这堆桃子的个数。
解:
设第n天的桃子数为x(n),则根据题意可写出递归公式 1 (n=10) x(n)=
(x(n+1)+1) * 2 (n<10) 据此可以写出递归函数。 程序代码如下: #include
int x(int n);
printf(\第一天的桃子数为:%d\\n\} int x(int n) {
int total; if(n==10) total=1;
else total=(x(n+1)+1)*2; return total;
} 二、变量的作用域、局部变量与全局变量
变量的作用域是指变量在程序中的有效范围。C语言中的变量,按作用域范围可分为两种:局部变量和全局变量。
?、局部变量(内部变量)
在一个函数内部说明的变量是内部变量,它只在该函数范围内有效。只有在包含变量说明的函数内部,才能使用被说明的变量,在此函数之外就不能使用这些变量了。所以内部变量也称“局部变量”。 局部变量的作用域被限定在其所定义的局部范围中。
?、关于局部变量的作用域还要说明以下几点: ①主函数main()中定义的变量是内部变量,也只能在主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义的内部变量。因为主函数也是一个函数,与其它函数是平行关系。
②形参变量也是内部变量,属于被调用函数;实参变量,则是调用函数的内部变量。
③在同一个作用域中不可定义同名变量,但在不同的作用域中可以定义同名变量,因为它们代表不同的对象,分配不同的单元,互不干扰,不会发生混淆。
④在复合语句中也可定义变量,其作用域只在复合语句范围内。 ?、全局变量(外部变量)
①在函数外部定义的变量称为外部变量。
外部变量不属于任何一个函数,其作用域是:从外部变量的定义位置开始,到本文件结束为止。 ②外部变量可被作用域内的所有函数直接引用,所以外部变量又称全局变量。 练习7_5:输入长方体的长(l)、宽(w)、高(h),求长方体体积及正、侧、顶三个面的面积。 解:/*功能:利用全局变量计算长方体的体积及三个面的面积*/ int s1,s2,s3;
int vs(int a,int b,int c) {
- 22 -
int v;
v=a*b*c; s1=a*b; s2=b*c; s3=a*c; return v;
}
main() {
int v,l,w,h;
printf(\: \scanf(\v=vs(l,w,h);
printf(\}
三、变量的存储属性
1、静态存储变量和动态存储变量
从变量的生存期(即在内存中存在时间)来看,变量可分为静态存储变量和动态存储变量。 ①静态存储变量:在系统编译程序时就分配存储单元,直至整个程序结束。
②动态存储变量:在程序执行过程中使用它时才分配存储单元,使用完毕立即释放。 2、变量的存储类型
变量存储类型是指变量在内存中的存储方式,分为静态存储和动态存储。
从变量的存储方式来看,变量分为auto(自动)变量、register(寄存器)变量、extern(外部变量)、static(静态变量)4种。
自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式。 ①自动变量:类型说明符为auto(可以省略),缺省时,凡未加存储类型说明符的局部变量都有是自动变量。
自动变量属于动态存储方式,其作用域和生存期都局限于定义它的程序体内(函数或复合语句),因此不同的程序体中允许使用同名的变量而不会混淆。
②寄存器变量:类型说明符为register,存放在CPU的寄存器中,使用时不需要访问内存,而直接从寄存器中读写,这样可提高效率。
③外部变量:类型说明符为extern,又称为全局变量。
④静态变量:类型说明符为static,分为静态局部变量和静态全局变量。
练习7_6、运行以下程序,写出运行结果,注意静态局部变量和动态局部变量的特点。 #include
auto a=0; int b=0; static c=0;
extern d; /* 因为变量d定义在后,需对变量d进行声明 */ a++;b++;c++;
return a+b+c+d; }
int d=10; /* 定义变量d为全局变量 */ void main() {
int i; int d=8;
for(i=1;i<=3;i++)
printf(\第%d次调用fun()函数的值:%d,变量d的值:%d\\n\
- 23 -
}
运行结果:
第1次调用fun()函数的值:13,变量d的值:8 第2次调用fun()函数的值:14,变量d的值:8 第3次调用fun()函数的值:15,变量d的值:8 注意:
在第二次调用fun()函数时,静态变量C的初值不再是0,而是1(因为静态变量C的值不释放) 四、编译预处理
所谓编译预处理是指,在编译之前处理,即在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。
1、宏定义与符号常量
在C/C语言中,“宏”分为无参数的宏(简称无参宏)和有参数的宏(简称有参宏)两种。 ?、无参宏定义
? 无参宏定义的一般格式
#define 标识符 语言符号字符串
其中:“define”为宏定义命令;“标识符”为所定义的宏名,通常用大写字母表示,以便于与变量区别;“语言符号字符串”可以是常数、表达式、格式串等。
? 使用宏定义的优点
①可提高源程序的可维护性 ②可提高源程序的可移植性
③减少源程序中重复书写字符串的工作量 ? 说明
①宏名一般用大写字母表示,以示与变量区别。但这并非是规定。 ②宏定义不是C语句,所以不能在行尾加分号。
③宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。
?、符号常量
在定义无参宏时,如果“语言符号字符串”是一个常量,则相应的“宏名”就是一个符号常量。 恰当命名的符号常量,除具有宏定义的上述优点外,还能表达出它所代表常量的实际含义,从而增强程序的可读性。
?、有参宏定义
? 带参宏定义的一般格式
#define 宏名(形参表) 语言符号字符串 ? 带参宏的调用和宏展开 ①调用格式:宏名(实参表)
②宏展开:用宏调用提供的实参字符串,直接置换宏定义命令行中、相应形参字符串,非形参字符保持不变。
2、文件包含
?、文件包含的概念
文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。 ?.文件包含处理命令的格式
#include “包含文件名” 或 #include <包含文件名> 两种格式的区别仅在于:
①使用双引号:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定的“包含文件目录”(由用户在配置环境时设置)去查找。
②使用尖括号:直接到系统指定的“包含文件目录”去查找。一般地说,使用双引号比较保险。 ?.文件包含的优点
- 24 -
一个大程序,通常分为多个模块,并由多个程序员分别编程。有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中。这样,凡是要使用其中数据或调用其中函数的程序员,只要使用文件包含处理功能,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动。
?.说明
①编译预处理时,预处理程序将查找指定的被包含文件,并将其复制到#include命令出现的位置上。
②常用在文件头部的被包含文件,称为“标题文件”或“头部文件”,常以“h”(head)作为后缀,简称头文件。在头文件中,除可包含宏定义外,还可包含外部变量定义、结构类型定义等。
③一条包含命令,只能指定一个被包含文件。如果要包含n个文件,则要用n条包含命令。 ④文件包含可以嵌套,即被包含文件中又包含另一个文件。
第八章 指针
▲一、指针和指针变量的概念 1、指针──即地址
一个变量的地址称为该变量的指针。取变量地址的运算符是&,通过变量的指针能够找到该变量。
2指针变量──专门用于存储其它变量地址的变量 ▲二、指针变量的定义与应用
?、指针变量的定义:[存储类型] 数据类型 *指针变量[, *指针变量2??]; 如float *p(缺省存储类型说明,表示指针变量p的存储类型是auto型) ?、取地址运算(&)和指针运算(*) 取地址运算的格式:&变量
指针运算(取内容运算)的格式:*指针变量(表示取指针变量所对应的目标变量的内容) 注:
①指针变量有自己的地址,它的内容也是一个地址。在C语言中,说p指向x,意味着变量p的内容是变量x的地址。
②由于指针的数据类型实际上是指定指针所能指向对象的数据类型,所以不同数据类型的指针变量不能相互赋值。
练习8_1:#include
int a,b; int *p1,*p2; a=100; b=10; p1=&a; p2=&b;
printf(\printf(\printf(\printf(\printf(\
printf(\}
练习8_2 写出以下程序的输出结果 #include
- 25 -