C语言程序设计 第八章 函数.

Slides:



Advertisements
Similar presentations
CSIM, PU C Language Introduction to the C Programming Language 重覆敘述 (for,while,break,continue) 適合重複性的計算或判斷.
Advertisements

C语言程序设计 主讲教师 :张群燕 电话:
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 博碩文化:
第一章 C语言概述 计算机公共教学部.
Introduction to the C Programming Language
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
C语言程序设计 课程 第5章 数组 主讲:李祥 博士、副教授 单位:软件学院软件工程系.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
第一章 C语言概述.
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
主讲教师:吴琼 微信群:C语言2016 QQ群: 密码scu2016 昵称:“真名+学号”
循环结构又称为重复结构:用来处理需要重复处理的问题,它是程序中一种很重要的结构。
函數 授課:ANT 日期:2009/3/24.
第3章 顺序结构程序设计 本章要点: 格式化输出函数──printf() 格式输入函数——scanf() 字符输出函数——putchar()
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
If … else 選擇結構 P27.
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
Chap 2 用C语言编写程序 2.1 在屏幕上显示 Hello World! 2.2 求华氏温度 100°F 对应的摄氏温度
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
程序设计专题一 结构化程序设计与递归函数 主讲教师: 刘新国.
第八章 函数.
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
Introduction to the C Programming Language
C语言 程序设计基础与试验 刘新国、2012年秋.
期中考试成绩分布 《程序设计》-2017年秋.
計數式重複敘述 for 迴圈 P
第三章 顺序结构程序设计 主讲教师 贾月乐 电话:
第5讲 结构化程序设计(Part II) 周水庚 2018年10月11日.
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
第4章 顺序程序设计.
第0章作业: 教材P12-练习与实践 1.写出用符号’*’输出描绘汉字”大”的流程图。
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
第 二 章 数据类型、运算符与表达式.
C语言复习2----函数.
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
浙江长征职业技术学院—计算机与信息技术系—相方莉制作
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
Chap 5 函数 5.1 计算圆柱体积 5.2 数字金字塔 5.3 复数运算.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
輸出與輸入(I/O).
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
C程序设计.
第5章 函 数.
C语言程序设计 李祥 QQ:
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第7章 程序的结构 四、生存期与存储属性 五、extern关键字与外部连接属性 六、static关键字与内部连接属性.
第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;
第二章 类型、对象、运算符和表达式.
Introduction to the C Programming Language
第三章 基本的輸出與輸入函數 (Basic Output & Input Function)
本节内容 指针类型.
Introduction to the C Programming Language
单片机应用技术 (C语言版) 第4章 C51程序设计入门
Chap 7 数 组 7.1 排序问题 7.2 找出矩阵中最大值所在的位置 7.3 进制转换.
第二章 数据类型、运算符和表达式 §2.1 数据与数据类型 §2.2 常量、变量和标准函数 §2.3 基本运算符及其表达式 目 录 上一章
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
C/C++基礎程式設計班 陣列 講師:林業峻 CSIE, NTU 3/14, 2015.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C程序设计 复习 1、计算机系统的组成 外部设备:输入、输出设备(同人打交道《十进制》)
函式庫補充資料 1.
C语言基础学习 从外行到入门.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

C语言程序设计 第八章 函数

主要内容 8.1 函数的定义和调用 8.2 变量的存储类型及作用域 8.3 函数的数据传递

概述 函数 函数是C语言程序的基本结构。C语言提供了许多函数。 它包括: I/O函数 数学函数 字符串函数、字符函数函数 时间(转换和操作)函数 接口函数 动态地址分配函数 目录函数 过程控制函数 字符屏幕和图形功能函数等。 用户可以根据需要选择使用。这一类函数称为库函数。库函数函数的引用的方法很简单,这里不赘述。

概述 库函数 库函数是由编译系统提供的现成函数。以前用过的scanf, printf, getchar等都是库函数。 在编写C程序时,尽可能多用库函数,以提高编程效率和质量。要调用某个库函数,需在程序的头部用包含命令(#include)将说明该函数原型的头文件包含进本程序中。使用库函数应注意以下几个问题: 函数的功能; 参数的数目、顺序和类型; 函数返回值类型; 需要使用的包含文件。

概述 常用的库函数 ex log10x 函数格式 所属函数库 功能 int getchar( ); stdio.h 标准输入一个字符 conio.h 不回显从键盘直接读入一个字符 int putch( int ch ); 向屏幕直接输出一个字符 char *gets( char * ); 标准输入一行文字 int puts( char * ); 标准输出一行文字(自动加换行) double sin( double ); math.h 正弦函数sin(x) double pow(double x,double y); xy double exp( double x ); ex double log( double x ); double log10( double x ); lnx log10x void exit( int status ); tdlib.h 强制结束程序

8.1 函数的定义和调用 函数的定义 函数的定义就是创造、编制函数。函数的定义过程就是编制函数的过程。 函数定义的格式 数据类型 函数名( 形参类型1 形参1,···形参类型n 形参n) { 说明语句; 可执行语句;   return(表达式) ;     } 例如:int myfun(int x, int y) { int z; if(x>y)z=x; z=y; return(z); }

8.1 函数的定义和调用 函数定义的说明 函数返回类型:若函数无返回值,或返回整型值, 可省略数据类型说明。 形参: 形参是函数接收外部数据的单向通道。函数调用时, 调用函数的实参将其数据传递给形参。 函数可以有多个或0个形参,各形参之间用逗号隔开。 形参可以是变量、指针或数组等; 形参不能是常量和表达式。形式参数是局部变量。作用域、生命期为函数体内。 函数名:函数名的命名规则同标识符的命名规则

8.1 函数的定义和调用 使流程返回主调函数,宣告函数的一次执行结束,在调用期间所分配的变量单元被撤消。 return语句:如果函数有返回值,则函数的最后一条语句就是 return语句。返回的意义是: 使流程返回主调函数,宣告函数的一次执行结束,在调用期间所分配的变量单元被撤消。 送函数值到调用表达式中。有些函数有返回值,有些函数没有返回值。 return语句的使用格式是: return; 或者 return (表达式); 或者 return 表达式;

8.1 函数的定义和调用 注意 return后的表达式的值类型必须与函数类型相同; 如果函数类型为空(void)类型,则函数体中可以不使用return语句,或使用不带参数的return。 一个函数允许有一个或多个return语句,流程执行到其中一个 return时即返回主调函数。如果有多个return语句,每个return后面的表达式的类型应相同。 如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据自动进行类型转换。 被调用函数中没有return语句,则函数带回一个不确定的值。建议用void标记函数的类型,则系统可保证函数不带回任何值,即禁止在调用函数中使用被调用函数的返回值。

8.1 函数的定义和调用 C语言准许定义“空函数”。 例如: dummy( ) { } 调用此函数, 什么工作也不做。它表明有一个函数, 尚未有具体的内容, 待以后将功能补充上去。一般在系统开发初期, 一些没开发出来的部分用此方法。

8.1 函数的定义和调用 函数的引用 函数定义好后,便可以在表达式中使用。 函数引用的格式 函数名(实参表列) 实参的作用是在程序发生函数调用时, 将其数据传递给函数的形参, 即向函数传送数据。 int fun1(x1,y1) { int z; z = x1 +y1; return( z ); } void main( ) { int s,x=2,y=6; s = fun1(x,y); printf (“%d”, s); 运行结果: 8

8.1 函数的定义和调用 实参与形参的关系 实参与形参的个数要相等。多个实参时要用逗号隔开。 实参与形参的数据类型相一致。 实参与形参的数据的传递是单向。即实参传给形参。同时是按排列顺序依次对应传递。 实参名与形参名可以相同,也可以不相同。 函数返回 如果函数需要返回值, 就用返回值带回调用函数的处理结果。返回值用赋值语句赋给主函数中的变量, 以接收其返回值。 返回值和接受返回值的变量的类型必须一致。

8.1 函数的定义和调用 函数调用 实参和形参的个数、类型和顺序必须一致。 实参可以是常量、变量名、数组名、数组元素或表达式。 在调用函数前, 必须先定义。

8.1 函数的定义和调用 函数调用的形式 在C语言中, 凡是能调用变量或表达式的地方, 均可调用函数。假设已定义了一个函数,即: 我们有如下三种形式调用: 函数调用语句形式,如: a=max(s1,s2); 这就是函数调用语句, 简称函数语句。 在表达式中引用,如: 例: y=max(x1,x2) / max(y1,y2); 函数调用函数,如: y=abs(max(rand( ),rand( ))); // 其中rand( ) 为随机函数。 int max(x,y) int x,y; { int z; z=(x>y)? x:y; return(z); }

8.1 函数的定义和调用 函数的声明 如果定义的函数在使用之后,则函数必须在使用前先声明。目的是告诉编译程序该函数返回值的数据类型, 以便编译程序能够检查对函数的调用是否正确,会不会发生错误的类型转换等。 函数说明的格式 数据类型 函数名( 形参类型 形参,…); 函数声明注意的问题 被调用函数的声明放在源文件头, 则该声明对整个源文件都有效 int f1( ); int f2( ); main( ) {… f1( ); f2( ); … } main( ) { int f1( ); int f2( ); … f1( ); f2( ); } int f1( ) { ... f2( ); } int f2( ) { … 函数f1中没有对函数f2进行说明,其引用是错误的。 √ √ ×

8.1 函数的定义和调用 如果被调用函数在调用函数内部声明, 则该声明仅对该调用函数有效。如果被调用函数是在函数外声明, 则该声明对以后的所有调用都有效。 void main( ) { float max(float a, float b, float c ); float x,y,z,m; scanf(“%f %f %f”,&x,&y,&z); m=max(x,y,z); printf(“\n%f:”,m); } float max(float a, float b, float c) { float result; result=a; if(result<b) result=b; if(result<c) result=c; return(result); 函数声明 float max(float a, float b, float c ); 函数使用 m=max(x,y,z); 函数max( )定义 float max(float a, float b, float c) { float result; result=a; if(result<b) result=b; if(result<c) result=c; return(result); }

8.1 函数的定义和调用 如果调用函数和被调用函数是在同一个源文件中, 而且程序中被调用函数是在调用函数之前已定义, 此时可以省略被调用函数的声明。 float max(float a, float b, float c) //先定义 { float result; result=a; if(result<b) result=b; if(result<c) result=c; return(result); } void main( ) { float x,y,z,m; scanf(“%f %f %f”,&x,&y,&z); m=max(x,y,z); //后使用,所以不用声明 printf(“\n%f:”,m);

8.1 函数的定义和调用 如果所有被调用函数的说明都是在源文件开头, 则在该源文件内的所有调用函数中不必再对被调用函数声明。 如果所有被调用函数的说明都是在源文件开头, 则在该源文件内的所有调用函数中不必再对被调用函数声明。 float f1( ); float f2( ); main( ) { … f1( ); … f2( ); } float f1( ) { … } float f2( ) 声明函数 f1、f2 定义函数 f1 定义函数 f2

8.1 函数的定义和调用 如果被调用函数的声明在源文件中间且在所有函数之外某处被说明时, 则在被说明之后引用它时, 不必再声说明; 但在被说明之前调用它时, 需对其进行说明。 如果函数的返回值是整型或字符型时, 可省略说明。

8.1 函数的定义和调用 例1 编制求两数最大值的程序。 #include<stdio.h> void main( ) 例1 编制求两数最大值的程序。 #include<stdio.h> void main( ) { float max( ); //函数声明 float a, b; scanf(“%f, %f ”,&a,&b); printf(“max is %f ”, max(a,b) ); //函数使用 } float max(float x, float y) // 函数定义 { if (x>y) return x; else return y; 运行结果: 5.8 3.2 ←┘ max is 5.8

8.1 函数的定义和调用 思路:对输入的整数, 先求其绝对值, 然后分解各位上的数字,边分解边累加, 直到完毕。 请输入一个整数:456 例2 编程 计算任一输入整数的各位数字之和,请用函数的方法处理。 思路:对输入的整数, 先求其绝对值, 然后分解各位上的数字,边分解边累加, 直到完毕。 #include<stdio.h> #include “math.h” int func(int num); void main( ) { int n; printf(“请输入一个整数: "); scanf("%d",&n); printf(“result:%d\n",func(n)); } int func(int num) { int s=0; num=abs(num); do { s=s+num%10; num=num/10; } while(num); return s; 请输入一个整数:456 result: 15

8.1 函数的定义和调用 例3 编制求n! 的函数。 #include<stdio.h> float factorial(int n) { float product; for( product=1;n>0;n--) product*=n; return(product); } void main() { int n; printf(“请输入一个整数:"); scanf("%d",&n); printf("n! = %e\n",factorial(n)); 运行结果: 请输入一个整数:6 ←┘ n! = 7.200000e+002

8.1 函数的定义和调用 函数的嵌套调用 C函数不能嵌套定义,但允许嵌套调用,即被其他函数调用的函数可以调用另一个函数。请看示意图: void main() { int i; i = num1(); … } int num1() { int j; j = num2(); … } int num2() { … }

8.1 函数的定义和调用 嵌套调用示例:计算 s = 1!+2!+3!+ … + 20! = ? 思路:编写一个主函数和两个子函数, 嵌套调用。 #include<stdio.h> void main() { double sum(int n) ; printf("s = %-12.5le\n", sum(20) ); } double sum(int n) { double fa(int k) , s=0; int i; for (i=1; i<=n; ++i) s = s + fa(i) ; return s; double fa ( int k ) { int i; double t; t = 1; for ( i = 1; i<=k; ++i) t*=i ; return t; 运行结果: S = 2.56133e+018

8.1 函数的定义和调用 函数的递归调用 所谓函数的递归调用,就是函数直接或间接地调用自己。在设计递归函数时应当考虑到递归的终止条件。 递归过程不应无限制地进行下去,不应该出现无终止的递归调用,而只应出现有限次数的、有终止的递归调用。当调用若干次以后,就应当到达递归调用的终点得到一个确定值,然后进行回代,回代的过程是从一个已知值推出下一个值。实际上这是一个递推过程。 递归总是由两部分组成的:递归方式和递归终止条件。 递归三要素 递归形式 递归规则 递归终结条件

8.1 函数的定义和调用 1 当 n=1 或 n=0时 例4 计算 n! = n(n-1)! 当n>1时 #include<stdio.h> float fa(int n) { float t; if (n== 1 || n==0) t =1 ; else t= n* fa(n-1) ; return t ; } void main() { int i ; scanf(”%d” , &i ); if (i<0) printf(”Data error !”) ; else printf(”%d ! = %-16.0f”, i, fa(i) ) ; 说明: 递归包括“回推”和“递归” 需有结束递归过程的条件

8.1 函数的定义和调用 递推 回归 4 * fa(3) 3 * fa(2) (4* 3* 2*1) 2* fa(1) (3* 2*1) 1 例5 计算 n! = 1 当 n=1 或 n=0时 n(n-1)! 当 n>1时 计算 fa(4) 递推 4 * fa(3) 输出 (4* 3* 2*1) 3 * fa(2) (4* 3* 2*1) 2* fa(1) (3* 2*1) 1 回归 2*1

8.2 变量的存储类型及作用域 对变量的访问就是对内存的访问。在C语言中变量的存储是有规定和区别的。 auto :自动型或堆栈型。 register:寄存器型。 static:静态型。 extern:外部型或全局型。 例如:auto int x; x 为自动变量。 static float y; y 为静态变量。

8.2 变量的存储类型及作用域 C 语言的存储空间 一般包括三部分: 程序区:存放执行程序的代码和static 静态变量; 静态存储区:存放程序的extern 外部变量、static 静态变量,其存放的数据在程序执行的过程中不释放,所对应变量值是不变的。 动态存储区(运行栈):程序运行时,存放数据的空间所对应变量是变化的。C语言程序在运行时,系统分配一个运行栈,存放以下数据: 函数调用时,保存调用现场的数据, 如返回点、寄存器中的值等。 函数调用时,存放被调用函数的形参。在函数调用时, 给形参分配存储空间, 以存放调用时传送给被调用的实参数据。 存放函数的返回值等。 为auto自动变量(register寄存器变量)分配存储空间。

8.2 变量的存储类型及作用域 用户区 存储器 存放执行程序的代码和静态变量 存放 static变量、 extern变量 存放auto变量( register变量) 函数的返回值、被调用函数的形参、保存调用现场的数据。 存储器

8.2 变量的存储类型及作用域 几个名词 静态变量:存储在静态存储区, 程序执行中始终不释放 动态变量:存储在动态存储区, 程序执行时 根据需要释放 内部变量:在函数或分程序内定义的变量。作用区域是整个函数或分程序 局部变量:内部变量都是局部变量。 外部变量:在函数或分程序外部定义的变量 全局变量:在程序开始定义的外部变量。作用区域是整个程序。 变量的作用域:变量在程序中的使用范围。 变量的生命期:程序中给变量分配的存储空间所保存数据的时间段 变量的可见性:存储器数据可操作时为可见的, 否则为不可见。

8.2 变量的存储类型及作用域 自动型变量(auto型) 概念:也叫局部变量。编译系统为自动型变量分配的是动态存储空间。运行程序如果离开了其作用域,,其变量的存储空间就释放, 故为动态变量。 定义格式: [auto] 数据类型 变量名;//auto可省略 定义的位置:在函数或分程序的开始位置。 性质:自动型变量是局部变量。作用范围限于函数或分程序内。该函数或分程序执行结束时,变量释放其存储空间,变量中的数据消失。在程序中,一般把计算或处理的中间结果的数据定义为自动型变量。

8.2 变量的存储类型及作用域 #include<stdio.h> float x,y; { int i,j; char c1,c2; double d1,d2; int m,n; int u,v; { … auto int k; … } x,y 的作用域 { } 对于这一对花括号 i,j,c1,c2是内部变量 i,j,c1,c2 的作用域 { } 对于这一对花括号 i,j,c1,c2是外部变量 d1,d2,m,n,u,v 的作用域 K的作用域

8.2 变量的存储类型及作用域 例: float factorial(int n ) { float product; for(product=1;n>0;n--) product*=n; return(product); } void main( ) { float factorial( ); int k; float sum; for(k=1,sum=0;k<=10;k++) sum=sum+factorial(k); 10 printf(“ n!=%e\n”,sum); n=1 变量 n和变量 product是自动变量 它们的作用域、生命期是整个factorial函数 当函数调用结束,函数返回值带回主函数后, 释放其存储空间,变量 n和变量product的数据消失。 此函数说明可以省略,因为定义在先,使用在后

8.2 变量的存储类型及作用域 寄存器型变量(register型) 概念:是把变量的数据存放在计算机CPU的寄存器中的变量。 定义的位置:在函数或分程序的开始的位置定义,先定义后引用。 存放数据的类型:int型、 short型、 char型。不能为其它类型 性质:存器变量是局部的动态变量。它的作用域、生命期局限在函数或分程序内, 函数或分程序执行结束时, 寄存器变量就被释放, 寄存器变量中的数据消失 适用场合:使用频繁的变量, 如把循环变量定义为寄存器变量,可以大大提高程序处理的速度,因为CPU对寄存器的读写速度远远快于对内存读写的速度 准许使用的数量:一般2-4个,视计算机类型而定。

8.2 变量的存储类型及作用域 x 例5 求  n3 =13+23+33+43+.. ..+n3 的值。 n=1 main( ) { int n; register int i,sum; printf(“Enter n:”); scanf(“%d”,&n); sum=0; for(i=1;i<=n;i++) sum=sum+i*i*i; printf(“sum=%d”,sum); } 运行结果: Enter n: 10<CR> sum=3025 变量n是自动型变量 变量i,sum是寄存器变量 变量i、sum、 n的作用域

8.2 变量的存储类型及作用域 静态型变量(static型) 概念:在静态存储区存放的变量。所分配的存储空间在整个程序运行中自始至终归该变量使用, 自始至终都不释放。静态变量分内部静态变量和外部静态变量两种。 内部静态变量 在函数或分程序内定义, 仅在定义它的函数或分程序内使用 内部静态变量定义格式: static 数据类型 变量名表 内部静态变量定义的位置:在函数或分程序内的开始位置 内部静态变量的性质:局部的可见性、全局的生命期 作用域:局部。函数外不可见。但其数据不释放不消失。 生命期:全局。在整个程序的执行过程中,内部静态变量数据当函数调用结束时并不消失,下次调用继续使用原保留值

8.2 变量的存储类型及作用域 请看下面示例: float add(x,y) float x,y; { static float z; z=z+x+y; return(z); } main( ) { float s,x=2,y=3; s=add(x,y); static 型变量在程序编译时,自动赋初值0 变量 z在函数结束时,并不释放,保留原值 S=5 S=10

8.2 变量的存储类型及作用域 外部静态变量 在函数外部定义的变量。其作用域是定义它的源文件。 定义格式(与内部静态变量的定义相同): static 数据类型 变量名表 定义的位置:在源文件的开始和所有函数之外定义。 作用域:是定义它的源文件。 生命期:是程序的整个执行过程。外部静态变量在编译时,在包含它的源文件所在的程序代码区中为其分配存储空间,该空间在整个程序执行过程中都归该变量所有,直到程序执行结束时才释放。 不同源文件中外部静态变量可以同名,各文件的外部静态变量有其自己的存储空间,同名变量不会冲突。

8.2 变量的存储类型及作用域 /* file1.c */ static int x,y; main( ) { ... } fun( ) /* file2.c */ static int x,y; fun1( ) { ... } fun2( ) 文件file1.c和文件file2.c中的同名外部静态变量 x, y互不干扰。 外部静态变量提供了把数据隐藏起来的一种手段, 使得外部文件不能访问它们, 也使不同源文件的同名外部变量不会冲突。

8.2 变量的存储类型及作用域 例6 读程序, 写出程序运行结果。 #include<stdio.h> void main() 例6 读程序, 写出程序运行结果。 #include<stdio.h> void main() { int k=1; static int x=10; void other(); printf("\n----main----\n"); printf("k=%d x=%d\n",k,x); other(); printf("----main----\n"); printf("k=%d x=%d\n",k,x); } void other() { int k=100; static int x=200; x+=100; printf("----other----\n");

8.2 变量的存储类型及作用域 外部型变量(extern型) 外部型变量是全局的静态的变量,它在函数之外定义。 定义的位置:在函数之外定义。 作用域:全局。在静态存储区为它分配存储空间。所分配的存储空间在整个程序执行过程始终归该变量所有,其值不会消失。对整个程序中的所有函数都可见 生命期:整个程序。 注意: 如果外部变量是在源文件中各个函数之前定义,则该源文件中的各函数都可以使用它,不需指定为extern 在一个源文件中定义的外部变量,可以在另一个源文件中引用,但必须在另一个源文件中用extern进行说明。

8.2 变量的存储类型及作用域 file1.c int x,y; main( ) { ... } fun( ) file2.c extern int x,y; f1( ) { y=x*x+1; .... } f2( ) { ... printf(%d %d”,x,y); ... x,y是文件file1.c中定义的变量。在文件file2.c中必须对变量x,y用extern int x,y进行说明, 然后file2.c中的各函数才可以使用他们。

8.2 变量的存储类型及作用域 如果外部变量与某函数内的局部变量同名,则在该函数内的同名变量的作用域内,局部变量有效,而外部变量暂不起作用。

8.2 变量的存储类型及作用域 例7 读程序,写出程序运行结果。 运行结果: j=10 j=20 例7 读程序,写出程序运行结果。 #include<stdio.h> int i=10; void main() { int j=0; int func(); j=func(); printf("j=%d\n", j ); } int func() { int k=0; k=k+i; i=i+10; return(k); 运行结果: j=10 j=20

8.2 变量的存储类型及作用域 静态函数、外部函数使用场合 静态函数局限于它所在的源文件, 对别的源文件中的函数不能引用。所以不同源文件中的内部函数可重名。 外部函数的作用域是整个程序, 在该作用域内的任何其它函数都可引用。 静态函数说明格式: static [数据类型] 函数名 ( ); 外部函数说明格式: [extern] [数据类型] 函数名( );

8.3 函数的数据传递 C语言函数间数据的通讯有如下方法: 参数传递方式,包括传值方式和传址方式; 函数返回值; 全局变量; 文件。 8.3 函数的数据传递 C语言函数间数据的通讯有如下方法: 参数传递方式,包括传值方式和传址方式; 函数返回值; 全局变量; 文件。 传地址方式 方法:它是把数据存放的地址传递给被调用函数的形参。这种方式一般以地址量作实参,如数组名或指针变量等;形参也是数组名或指针变量。 特点:一次可传递多个数据。

8.3 函数的数据传递 例8:以数组名为实参、形参的函数调用。 #include<stdio.h> 8.3 函数的数据传递 例8:以数组名为实参、形参的函数调用。 #include<stdio.h> int add ( int a[20], int n ) { int i,result=0; for(i=1;i<n;i++) result += a[i]; return result; } void main() { int a[20],i=0,sum=0; printf(“请输入整数到数组a[ ](结束:输入0):) \n"); while(a[i++]!=0 && i<20) scanf("%d",&a[i]); i=i; sum=add( a, i ); printf("\nsum=%d\n",sum); 请输入整数到数组a[ ](结束:输入0): 2 3 4 5 0 Sum = 15

8.3 函数的数据传递 利用全局变量传递数据 方法:在一个程序中, 全局变量对所有函数都是可见的, 可以利用它来实现函数间的通讯。 8.3 函数的数据传递 利用全局变量传递数据 方法:在一个程序中, 全局变量对所有函数都是可见的, 可以利用它来实现函数间的通讯。 优点: 方法简单, 程序的运行效率高 缺点:各个函数都可以对全局变量进行操作, 出错后很难确定错误发生的位置。所以过多的全局变量不利于程序的调试和维护。这种方式不提倡使用。