c语言讲稿(ch7部分)
- 格式:doc
- 大小:77.00 KB
- 文档页数:15
4、函数调用时实参的求值顺序(1)自定义函数的实参求值顺序标准没有规定,不同编译系统不一致。
TC:自右向左 VC:自左向右例:float aver(float x, float y, float z){ return (x+y+z)/3;}main(){ int x=1;printf(“%f”,aver(x+1, x, x++)) ;}TC运行结果:2 VC运行结果:1.333333(2) 系统库函数的实参求值顺序根据函数原型判断实参求值顺序:•函数原型为:函数类型 Cdecl 函数名(形式参数表);——该函数用C语言编写,依据编译系统不同而不同•函数原型为:函数类型 Pascal 函数名(形式参数表);——该函数用pascal语言编写,自左向右求值例如:math.h中包含以下函数原型:double _Cdecl pow(double x, double y) ;三、函数声明(function declaration)也称函数原型(function prototype)1、何时需要函数声明当函数定义在后,函数调用在前时需要在调用之前声明该函数。
例:float aver( int x,int y,int z);ave函数声明main(){ int x=1;printf(“ %f ”,aver (x+1, x, x++)) ;}float aver( int x,int y,int z){ return (x+y+z)/3; }2、函数声明一般格式函数类型函数名(数据类型 [形参变量名],数据类型 [形参变量名], . . .);形参变量名可缺省或换名。
例:函数定义:float aver( int x,int y,int z){ return (x+y+z)/3;}aver函数声明的几种形式:float aver( int x,int y,int z);float aver( int ,int ,int );float aver( int a ,int b,int c);3、缺少函数声明时编译器的处理方式•首先遇到函数定义时保存该函数的返回值类型和参数的个数及类型,用于后面调用该函数时检查实参的个数及类型。
第1章 C 程序概述人与计算机交换信息是要用语言来交流的,这种语言称为计算机语言。
用计算机语言编写的代码称为程序。
计算机的工作是受程序控制的,而从计算机角度来说,程序是用某种计算机能理解并执行的计算机语言来描述解决问题的方法步骤。
程序设计语言经历了从机器语言、汇编语言到高级语言这样一个发展过程。
1.机器语言:计算机刚诞生时,还没有可以用来方便地指挥计算机工作的程序,计算机程序是直接用它能识别的二进制指令来书写的。
这种程序设计语言就是机器语言。
它直接以计算机硬件产生作用的,所以不同型号的计算机的“机器语言”又不一样,因此它被称为低级语言,很难被人掌握,只有少数专业人员能使用。
2.汇编语言:实际上是一种符号化的机器语言。
在汇编语言中每条机器指令对应一个符号化的指令。
如:用ADD代表机器二进制的加法运算。
因为加法用二进制的10110110的机器语言代表,而用英文单词更简捷且好记多了。
不过,用汇编语言编写的程序要翻译成机器语言才能被计算机执行。
且也依赖于机器。
3.高级语言:由于汇编语言和机器语言都是面向机器的语言,而且在程序的书写形式上很难直观地反映出程序设计者的思路,因此人们发明了与人类的自然语言非常接近的高级程序设计语言。
高级语言不仅易学,易用,而且写出的程序更加简练,同一个程序还可以用在不同型号的机器上。
比如说,我们要求两个数的和,在高级语言中可以用一个很简单的语句C=A+B;来表示,但在汇编语言或者机器语言中,这可能就是几条甚至几十条机器指令构成的一个实现加法的程序,常人要读懂它也不是那么容易。
但是,用高级语言编写的程序不能被计算机直接理解和执行,而必须先由这种语言的编译程序或者解释程序翻译成机器指令,然后再让计算机执行机器指令。
C语言的历史20世纪70年代初期出现的FORTRAN,ALGOL和PASCAL语言是反映了结构化程序设计思想的高级语言,PASCAL它在大学和研究所中流传较广曾为国内外计算机(应用)专业学生的入门语言。
c语言讲稿(ch7部分)第七章函数第一节软件的分层模块化一、分层模块化主要思想1、按功能将程序划分若干独立模块,模块之间具有层次关系,上层模块可调用下层模块。
例:一个简单学籍管理程序,经过需求调查和分析后,设计出如下模块结构:2、对于模块的基本要求每个模块功能单一。
用三种基本结构构造模块内的程序代码段。
每个模块有名字每个模块的接口参数应尽量简单模块之间尽可能互相隔离(没有数据依赖性)除主模块由操作系统调用外,其它模块的调用一般应遵守:上级模块调用下级模块3、模块化程序的开发逐个模块进行设计、编码和调试开发团队分工合作4、c语言实现模块结构程序的支持机制(函数)函数定义——模块函数名——模块名函数的形式参数——模块接口函数调用——模块调用第二节 C 语言函数简介一、函数分类1、根据定义分类系统预定义函数(库函数)不需用户定义,可多次调用用户自定义函数需要用户一次定义,可多次调用2、根据参数分类无参函数定义和调用时均不带参数有参函数定义和调用时带一个以上的参数3、根据返回值分类有返回值函数函数调用结束时带值返回到主调函数无返回值函数函数调用结束时不带任何值返回到主调函数二、函数一般特性1、函数的定义在一个源程序中:必须有一个也只能有一个main函数定义(函数名是规定的,函数体是自定义的)。
可以有多个相互独立的其它函数定义。
在一个函数定义的函数体中不允许出现另一个函数定义(嵌套定义)。
2、函数的调用发出运行程序命令后操作系统调用执行main函数。
在一个函数定义的函数体中可以调用另一个函数(嵌套调用),也可以调用函数自身(直接递归调用)。
main函数也可以被其它函数调用(间接递归调用),但一般不这样做。
3、函数的返回一个函数被调用后,一旦执行到return语句或函数体的最后一个“}”时,自动返回到主调函数处继续执行后续指令。
函数返回时可以带值或不带值。
第三节函数的定义、调用和声明一、函数定义(function definition)1、函数定义格式[存储类型] [函数类型] 函数名([const] [存储类型] 数据类型形参变量名1, . . .) { 变量声明序列语句序列}下划线部分为形式参数表特殊情况:无参函数:形式参数表中只放一个void,或者为空无返回值函数:函数类型为void缺省情况:函数类型缺省时为int,形参缺省时为void2、函数类型代表函数返回值类型。
第七章函数第一节软件的分层模块化一、分层模块化主要思想1、按功能将程序划分若干独立模块,模块之间具有层次关系,上层模块可调用下层模块。
例:一个简单学籍管理程序,经过需求调查和分析后,设计出如下模块结构:2、对于模块的基本要求•每个模块功能单一。
用三种基本结构构造模块内的程序代码段。
•每个模块有名字•每个模块的接口参数应尽量简单•模块之间尽可能互相隔离(没有数据依赖性)•除主模块由操作系统调用外,其它模块的调用一般应遵守:上级模块调用下级模块3、模块化程序的开发逐个模块进行设计、编码和调试开发团队分工合作4、c语言实现模块结构程序的支持机制(函数)函数定义——模块函数名——模块名函数的形式参数——模块接口函数调用——模块调用第二节 C 语言函数简介一、函数分类1、根据定义分类•系统预定义函数(库函数)不需用户定义,可多次调用•用户自定义函数需要用户一次定义,可多次调用2、根据参数分类•无参函数定义和调用时均不带参数•有参函数定义和调用时带一个以上的参数3、根据返回值分类•有返回值函数函数调用结束时带值返回到主调函数•无返回值函数函数调用结束时不带任何值返回到主调函数二、函数一般特性1、函数的定义在一个源程序中:必须有一个也只能有一个main函数定义(函数名是规定的,函数体是自定义的)。
可以有多个相互独立的其它函数定义。
在一个函数定义的函数体中不允许出现另一个函数定义(嵌套定义)。
2、函数的调用发出运行程序命令后操作系统调用执行main函数。
在一个函数定义的函数体中可以调用另一个函数(嵌套调用),也可以调用函数自身(直接递归调用)。
main函数也可以被其它函数调用(间接递归调用),但一般不这样做。
3、函数的返回一个函数被调用后,一旦执行到return语句或函数体的最后一个“}”时,自动返回到主调函数处继续执行后续指令。
函数返回时可以带值或不带值。
第三节函数的定义、调用和声明一、函数定义(function definition)1、函数定义格式[存储类型] [函数类型] 函数名([const] [存储类型] 数据类型形参变量名1, . . .) { 变量声明序列语句序列}下划线部分为形式参数表特殊情况:无参函数:形式参数表中只放一个void,或者为空无返回值函数:函数类型为void缺省情况:函数类型缺省时为int,形参缺省时为void2、函数类型代表函数返回值类型。
允许:5种基本类型,指针类型,构造类型,void(无值)3、形式参数(formal argument)•所有形式参数都是变量,简称形参变量•形参变量的类型可以是:5种基本类型、指针类型、构造类型(结构,联合)•函数体内不能再声明与形参变量同名的其他局部变量•形参变量的作用域为所在函数的函数体•形参变量只有在所在函数被调用期间才存在4、修饰词const限定被修饰的形参变量的值在函数体不能被改变。
例:float f(int x, const int y){ y++; scanf(“%d”,&y); (错)x=y; scanf(“%d”,&x); (正确)return y;}main(){ float a; a=f(1,2); . . . }5、函数返回与return 语句•当函数类型为非void时,函数调用结束后必定带一个值(基本类型)或一组值(结构类型)返回,返回值的类型由函数类型决定。
•return语句格式return e; 或 return ;(缺省e)( e:表达式,e值的类型应与函数类型相同或赋值兼容)•执行“return e;”语句返回一个确定的值(e的值)执行“return ;”语句返回一个不确定的值或不返回任何值•当函数类型为基本类型时,执行“r eturn e;”语句时只能返回一个数据。
若e值的类型与函数类型不同但赋值兼容,则e值的类型将被自动转换为函数类型后再返回。
•当函数类型为非void时,函数体中应当包含一个或多个会被执行到的return e;例:int f(int x,int y){ if(x%y)return 0;else return 1;}或将函数体改为:int flag;if(x%y)flag=0;else flag=1;return flag;以下函数缺少必要的return 语句,在vc系统编译时出现warning信息:not all control paths return a valueint f(int x,int y){ int fl;if(x%y)fl=0;else return 1;}•当函数类型为void时,函数体中可以不包含“return;”语句,也可以包含一个或多个会被执行到的“return ;”语句。
初学者易犯的错误(1)嵌套定义函数例:int f(int w){ int i,j;int g(int x) 函数定义嵌套{ int a=0,b=1;a++; b++;}}改正:去掉int g(int x)或将其改为if(w>0),则变成块嵌套•形式参数表错误(语法错)例:int f (int x, y){ . . . }•函数头部错误(语法错)例:int f (int x , int y);函数声明而非函数定义{ . . . }•函数体中出现与形式参数同名的变量声明(语法错)例: int f(int x){ float x; . . . }(5) 试图用一个return e;返回一个以上的值(语义错)例: return x,y;return x; return y;6、关于函数定义的建议(1) 函数头部不超过一行(接口尽量简单)(2) 若函数体中包含多个功能,应将该函数进一步划分为几个小函数(函数功能单一)。
二、函数调用(function call)1、函数调用格式有参函数:函数名(e1, … en)无参函数:函数名();():函数调用运算符函数名:作为操作数的标识符e1,… en: 实参表达式(简称实参)若函数有返回值,又称为函数调用表达式2、对实参的要求•实参与形参个数应当相同•实参与对应形参的类型应赋值兼容(类型相同或类型不相同但形参类型能被自动转换为实参类型)•e1,… en可以是常量、变量引用或任何表达式(包括函数调用表达式)例:int max(int x,int y,int z) { . . . }main(){ int a=4,b=5,c=6;c=max(3,c+1,max(b,c));}常见错误:main(){ int x=2,y;y=x(x+1);}编译报错信息:Call of non-function in function main3、实参与形参的数据类型(实参传递方式)•基本类型/算术类型(传单值方式)例:void swap(int x, int y) 声明x,y为算术型变量{ int z; z=x; x=y; y=z; }main(){ int a=1,b=2;swap(a,b);printf(“a=%d,b=%d”,a,b);}输出:a=1,b=2main函数调用swap函数时,将实参a、b的值复制到对应形参变量x、y中,形参变量x、y 中的值发生变化时,对应实参a、b中的值并不改变。
(2) 指针类型(传地址方式)例:void swap(int *x, int *y)声明x,y为指针型变量{ int z; z=*x; *x=*y; *y=z; }*x: 引用x指向的变量,这里为main函数中的变量a{ int a=1,b=2;swap(&a,&b);printf(“a=%d,b=%d”,a,b);}输出:a=2,b=1main函数调用swap函数时,将实参变量a、b的地址值复制到对应形参变量x、y中,swap 函数内通过x、y间接引用a、b,可以使a、b中的值发生变化。
(3)构造类型(传一组值方式)后续章节介绍4、函数调用时实参的求值顺序(1)自定义函数的实参求值顺序标准没有规定,不同编译系统不一致。
TC:自右向左 VC:自左向右例:float aver(float x, float y, float z){ return (x+y+z)/3;}main(){ int x=1;printf(“%f”,aver(x+1, x, x++)) ;}TC运行结果:2 VC运行结果:1.333333(2) 系统库函数的实参求值顺序根据函数原型判断实参求值顺序:•函数原型为:函数类型 Cdecl 函数名(形式参数表);——该函数用C语言编写,依据编译系统不同而不同•函数原型为:函数类型 Pascal 函数名(形式参数表);——该函数用pascal语言编写,自左向右求值例如:math.h中包含以下函数原型:double _Cdecl pow(double x, double y) ;三、函数声明(function declaration)也称函数原型(function prototype)1、何时需要函数声明当函数定义在后,函数调用在前时需要在调用之前声明该函数。
例:float aver( int x,int y,int z);ave函数声明{ int x=1;printf(“ %f ”,aver (x+1, x, x++)) ;}float aver( int x,int y,int z){ return (x+y+z)/3; }2、函数声明一般格式函数类型函数名(数据类型 [形参变量名],数据类型 [形参变量名], . . .);形参变量名可缺省或换名。
例:函数定义:float aver( int x,int y,int z){ return (x+y+z)/3;}aver函数声明的几种形式:float aver( int x,int y,int z);float aver( int ,int ,int );float aver( int a ,int b,int c);3、缺少函数声明时编译器的处理方式•首先遇到函数定义时保存该函数的返回值类型和参数的个数及类型,用于后面调用该函数时检查实参的个数及类型。
•首先遇到函数调用时将函数的返回值类型设定为int,当以后遇到该函数定义,若函数类型为非int,则编译报错:type mismatch in redefinition of …不检查实参的个数是否与函数定义的形参个数一致,也不管形参的数据类型是什么,按下列方式转换实参类型后传给对应形参:char/short int -> intfloat -> double4、函数声明的位置对函数调用的影响•放在调用之前,函数之外函数名的作用域为声明位置到文件结束•放在调用之前,函数之内函数名的作用域为声明所在函数四、函数之间数据传递的几种方式[方式1]int f(int x){ return x*x; }main(){ int a=2,b;b=f(a);}调用f函数时a->x,函数返回x*x->b特点:f函数可以接收多个值,但只能返回一个结果值,f与其他函数之间无数据依赖性。