
函数的调用
841 函数调用的一般形式
前面已经说过,在程序中是通过对函数的调用来执行函数体的,其过程与其它语言的子程序调用相似。
C语言中,函数调用的一般形式为:
函数名(实际参数表)
对无参函数调用时则无实际参数表。实际参数表中的参数可以是常数,变量或其它构造类型数据及表达式。各实参之间用逗号分隔。
842 函数调用的方式
在C语言中,可以用以下几种方式调用函数:
1 函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如:z=max(x,y)是一个赋值表达式,把max的返回值赋予变量z。
2 函数语句:函数调用的一般形式加上分号即构成函数语句。例如: printf ("%d",a);scanf ("%d",&b);都是以函数语句的方式调用函数。
3 函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。例如: printf("%d",max(x,y)); 即是把max调用的返回值又作为printf函数的实参来使用的。在函数调用中还应该注意的一个问题是求值顺序的问题。所谓求值顺序是指对实参表中各量是自左至右使用呢,还是自右至左使用。对此,各系统的规定不一定相同。介绍printf 函数时已提到过,这里从函数调用的角度再强调一下。
main()
{
int i=8;
printf("%d\n%d\n%d\n%d\n",++i,--i,i++,i--);
}
如按照从右至左的顺序求值。运行结果应为:
8
7
7
8
如对printf语句中的++i,--i,i++,i--从左至右求值,结果应为:
9
8
8
9
应特别注意的是,无论是从左至右求值, 还是自右至左求值,其输出顺序都是不变的, 即输出顺序总是和实参表中实参的顺序相同。由于Turbo C现定是自右至左求值,所以结果为8,7,7,8。上述问题如还不理解,上机一试就明白了。
843 被调用函数的声明和函数原型
在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。
其一般形式为:
类型说明符 被调函数名(类型 形参,类型 形参…);
或为:
类型说明符 被调函数名(类型,类型…);
括号内给出了形参的类型和形参名,或只给出形参类型。这便于编译系统进行检错,以防止可能出现的错误。
例81 main函数中对max函数的说明为:
int max(int a,int b);
或写为:
int max(int,int);
C语言中又规定在以下几种情况时可以省去主调函数中对被调函数的函数说明。
1) 如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明,而直接调用。这时系统将自动对被调函数返回值按整型处理。例82的主函数中未对函数s作说明而直接调用即属此种情形。
2) 当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数再作说明而直接调用。例如例81中,函数max的定义放在main 函数之前,因此可在main函数中省去对max函数的函数说明int max(int a,int b)。
3) 如在所有函数定义之前,在函数外预先说明了各个函数的类型,则在以后的各主调函数中,可不再对被调函数作说明。例如:
char str(int a);
float f(float b);
main()
{
……
}
char str(int a)
{
……
}
float f(float b)
{
……
}
其中第一,二行对str函数和f函数预先作了说明。因此在以后各函数中无须对str和f函数再作说明就可直接调用。
4) 对库函数的调用不需要再作说明,但必须把该函数的头文件用include命令包含在源文件前部。
85 函数的嵌套调用
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。其关系可表示如图。
图表示了两层嵌套的情形。其执行过程是:执行main函数中调用a函数的语句时,即转去执行a函数,在a函数中调用b 函数时,又转去执行b函数,b函数执行完毕返回a函数的断点继续执行,a函数执行完毕返回main函数的断点继续执行。
计算s=22!+32!
本题可编写两个函数,一个是用来计算平方值的函数f1,另一个是用来计算阶乘值的函数f2。主函数先调f1计算出平方值,再在f1中以平方值为实参,调用 f2计算其阶乘值,然后返回f1,再返回主函数,在循环程序中计算累加和。
long f1(int p)
{
int k;
long r;
long f2(int);
k=pp;
r=f2(k);
return r;
}
long f2(int q)
{
long c=1;
int i;
for(i=1;i<=q;i++)
c=ci;
return c;
}
main()
{
int i;
long s=0;
for (i=2;i<=3;i++)
s=s+f1(i);
printf("\ns=%ld\n",s);
}
在程序中,函数f1和f2均为长整型,都在主函数之前定义,故不必再在主函数中对f1和f2加以说明。在主程序中,执行循环程序依次把i值作为实参调用函数f1求i2值。在f1中又发生对函数f2的调用,这时是把i2的值作为实参去调f2,在f2 中完成求i2!的计算。f2执行完毕把C值(即i2!)返回给f1,再由f1返回主函数实现累加。至此,由函数的嵌套调用实现了题目的要求。由于数值很大,所以函数和一些变量的类型都说明为长整型,否则会造成计算错误。
当然可以!
C语言程序的最基本的模块就是函数,
该程序规定:任意函数都可以调用其它任意一个函数,包括函数本身;
1、函数调用自己本身, 这种称为递归;
通过递归,计算1+2+3++n值的代码:
2、自定义函数调用其它自定义函数的例子:
这个例子就是主函数调用自定义函数fun2,然后fun2调用另一个自定义函数fun1;
如果一个函数要使用参数,它就必须定义接受参数值的变量。
形式参数与实际参数
函数定义时填入的参数我们称之为形式参数,简称形参,它们同函数内部的局部变量作用相同。形参的定义是在函数名之后和函数开始的花括号之前。
调用时填入的参数,我们称之为实际参数,简称实参。
必须确认所定义的形参与调用函数的实际参数类型一致,同时还要保证在调用时形参与实参的个数出现的次序也要一一对应。如果不一致,将产生意料不到的结果。与许多其它高级语言不同,(是健壮的,它总要做一些甚至你不希望的事情,几乎没有运行时错误检查,完
全没有范围检测。作为程序员,必须小心行事以保证不发生错误,安全运行。
赋值调用与引用调用
一般说来,有两种方法可以把参数传递给函数。第一种叫做“赋值调用”(call
by
value),这种方法是把参数的值复制到函数的形式参数中。这样,函数中的形式参数的任何变化不会影响到调用时所使用的变量。
把参数传递给函数的第二种方法是“引用调用”(call
by
reference)。这种方法是把参数的地址复制给形式参数,在函数中,这个地址用来访问调用中所使用的实际参数。这意味着,形式参数的变化会影响调用时所使用的那个变量
将函数写在主程序后面,主函数前面应该声明,我从前是这样学的,现在的编译软件可能兼容了吧,如果函数多了声明也容易看,这个函数的声明就在main前面把int add(int x,int y);写上最好了,如果不用声明则将整个函数放在main以前,以后子函数多了也可以方便的看到定义了哪些子函数,如果程序很大,声明放在一个文件里,函数实现放在另一个文件里,好长时间没动了,当时好像老师是这么说过,main前面最好加类型int ,好给程序最后一个返回值比如return 0;我学的本来就不好,不在这里瞎指挥了,如果错了希望大家多多原谅,因为时间太长了,记不住了
float max(struct student stu)函数参数的类型为struct student
所以你在函数内部使用&stu[0]这种用法 把它当成数组用一定会出错的
至于为什么加上
ma=max(stu);/加上这个函数后就出错了,没它之前程序可以执行/
才报错,是因为你没有调用那个函数 函数不会被编译
建议修改max函数 如下
float max(struct student student)//这里函数参数不要和全局变量重名 会引起一些不必要的麻烦
{
int i;
float n;
n=average(student[0]);/为什么这边说illegal for struct/
for(i=0;i<5;i++)
if(n<average(student[i])) n=average(student[i]);
return n;
}
试试 我没编译 如果再有问题的话继续 我帮你改
互相反复调用,一方面是死循环,另一方面,系统资源堆栈会耗尽。
我们可以加一个循环控制条件,让它只循环有限次结束。
#include <stdioh>
int a=1,b=9;
int k=0,k_m=10; // 用k 记录次数,设最多次数为 k_m
int change();
int change1();
int main(){
change();
return 0;
}
int change(){
int i;
k++; if (k > k_m) return 1; // 次数满了,结束程序
for(i=0;i<2;i++) {
printf("a=%d\n",a);
change1();
}
return 0; // 正常返回0
}
int change1(){
int i1;
k++; if (k > k_m) return 2; // 次数满了,结束程序
for(i1=0;i1<2;i1++) {
printf("b=%d\n",b);
change();
}
return 0; // 正常返回0
}
这就没问题了。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)