`

第8章 函数(六)共享局部变量

 
阅读更多

声明:文中观点仅代表个人,其中文字、图片未经本人许可,不得部分或全部转载,违者所造成影响后后果自负!联系本人方式:80368704@qq.com QQ:80368704

对于你的孩子,你要保护她,但绝对不能让她完全的与世隔绝,那样,她就会成为白痴。同样,做为一个程序员,函数就像你的孩子,函数之间是要交流的。

我们已经知道,函数之间交流的就是数据,当然我们可以通过全局变量,将数据在函数之间交流共享,在本章程序5就是用全局变量实现了函数间a,b的共享。使用全局变量共享数据是一种办法。

下面我们看看被严密保护的局部变量的值,是如何在函数间实现共享的。我的描述就从把程序5的全局变量a,b变成了各函数的局部变量开始吧。

基本思路如下:

1、对main()函数的改造。

在main()函数中定义变量float a,float b;并用scanf()输入a,b的值。对于程序5来说就是将全局变量float a,b;移动到main()中,变成main()的局部变量。即:

main()

{

float a,float b;

scanf("%f%f",a,b);

在main()中调用max()的同时,为max()带上1份a,b值的拷贝,我们把max();语句变成max(a,b);就可以携带a,b了

于是有了如下的程序片段:

main()

{

float a,float b;

scanf("%f%f",a,b);

max(a,b);..........

在main()中调用min()的同时,为min()带上1份a,b值的拷贝<min(a,b);>

于是有了如下的程序片段:

main()

{

float a,float b;

scanf("%f%f",a,b);

max(a,b);

min(a,b);............

在main()中调用average();的同时,为average()带上1份a,b值的拷贝<average(a,b);>

main()

{

float a,float b;

scanf("%f%f",a,b);

max(a,b);

min(a,b);

average(a,b);

}

啥是值的拷贝啊?

按原物,一模一样再做一个新的出来来,这个新产生的物品,就是原物的拷贝,也叫副本或复制品。

以上基本思路就说完了。按这个思路,我们确保从main()带向其它3个函数的是a,b的拷贝,而不是变量a,b本身,于是,max(),min(),average()即使对带入的数据做了修改,也是对拷贝副本进行的,不会修改main()中的a,b。

2、 对于max()函数的改造。

我们需要在其密封外壳上撕开一道口子或叫开个天窗,以便从main()中调用语句max(a,b);带来的a,b值副本能穿过max()函数外壳,进入其内部。

于是,把max()后的()撕开撑大,变成max ( )

函数max()就变成如下了:

void max ( ) /*求任意2个数字的最大值。*/

{

float m;

m=a>b?a:b;

printf("%f/n",m);

}

人类的家开窗户,只是为通风透亮,但不想让蚊子,苍蝇进入,于是<就要有纱窗过滤,同样max()函数被开窗口后,也不是让啥数都能进,要明确指定哪类数能进。我们这个例子是要把main()中的a,b两个float类的数值送入max中,因此要明确指出只允许2个float的数进入。

于是,max( )变成了max(float ,float )相当于给max开的窗户上加个过滤纱窗噢。

void max(float ,float )/*求任意2个数字的最大值。*/

{

float m;

m=a>b?a:b;

printf("%f/n",m);

}

&;nbsp; 在a,b的副本穿过max()窗户的纱窗进入其内部后,必须要有个临时住所,专业些说,就是2个float数据必须被存放在临时空间中,我们为这两个临时空间起个名吧,起啥名呢?既然是接收main()的a,b的值拷贝,干脆把临时空间也叫a,b算了。

于是max(float ,float )就演变成了max(float a,float b)了。

void max(float a,float b)/*求任意2个数字的最大值。*/

{

float m;

&;nbsp; m=a>b?a:b;

printf("%f/n",m);

}

3、 同理我们把min()和average()也做了和max()同样的开窗手术,

&;nbsp; min()的函数首部变成了min(float a,float b)

&;nbsp; average()的函数首部变成了average(float a,float b)

完整的函数,就不写了,看下面程序6中吧。

完成上述改造后,我们就从程序5演变出了全新的程序6,如下:

程序6:

/********************************************************/
#include〈stdio.h〉

void max(float a,float b)
{printf("%f/n",a>b?a:b); } /*省略m,直接输出最大值*/

void min(float a,float b)
{printf("%f/n",a<b?a:b); } /*省略m,直接输出最小值*/

void average(float a,float b)
{printf("%f/n",(a+b)/2); } /*省略m,直接输出平均值*/

void main()
{
float a,b;
scanf("%f%f",&a,&b);
max(a,b);
min(a,b);
average(a,b);
}

4、main(),max(),min(),average()各有自己的a,b,

数学上把函数后括弧中的数称为函数的参数,我们也沿用了这种叫法。拿max()为例说明如下:

main() max( float a,float b )
{ {
max( a , b ); ............

} }

都是函数参数,但是有区别。

在main()中,max(a,b);语句将a,b值拷贝,带到函数max(float a,float b){...}的a,b中,

是main()中a,b的实际数值的拷贝。 被称为实际参数,简称实参

是从形式上说明了可进入max()的是2个float类的数值,以及进入max后将被存入临时变量a,b中。因此②被称为形式参数,简称形参

5、main()中max(a,b)中的实参将a,b的值拷贝带给了max(float a,float b){...}函数的形参float a,float b,即实参a,b为形参a,b传递了数值。我们称这种传递为值传递

C语言规定,这种值传递是单向的;即实参可把值传递到形参中,但形参不能将值反向传回实参。仍拿max()函数为例说明如下:

max(a,b); max(int a,int b)
① ← ----------X--- 反向传不行---------------------
↘________实参传值给形参____________↗

规定单向传递的目的,再次用main()和max()之间数值传递为例,说明如下:

首先,主函数main()用max(a,b);语句中的实参,将其a,b的值拷贝传入max(float a,float b){...}函数的float a,float b中,以便max()可以使用这两个数。

其次,单向传递确保max(float a,float b){...}函数对a,b值无论怎样修改,也不会反向传回main()中,保护了main()中的a,b的值不被max(float a,float b){...}修改。

至此,我们实现了main()中的局部变量a,b,能被max()函数读到,但不被其随意修改的想法;当然同样的道理,我们也实现了main()和min()、average()的数值单向传递。


6、函数的回应------返回值


每个人都知道,当我们请求别人做件事,能不能做总希望能给个答复吧

在上面的程序中,拿main()调用max()为例,其实就是main()想请max()函数,给它求最大值,但main()只能把数据传入它调用的函数max(),比如:

main()中调用语句max(a,b)把a,b的值传到float max(float a,float b){...}中;

相当于是建立起了单向的数据通道,如下所示:

main(){...}------------->float max(float a,float b){...}

如果拟人化的话,程序员是一个人,main()是一个人,max()是一个人,共3个人.

(1)、程序员请求main()求最大值.

(2)、main()请求max()给求一下最大值,于是main()把a,b给了max(),

(3)、max()求出最大值后,直接把最大值给了屏幕,也就是给了程序员看,

我们看到这个过程中,max()并没有给main()任何的答复,我要是main(),就希望max()好歹给各信儿,比如能不能求,求出来没有...........

那么,作为程序员,我就想,能否建立如下的双向数据通道:

main(){...}《-------------》float max(float a,float b){...}

这样max()可以返回信息给max(),于是main()就可以知道它调用max()后,是个啥情况,max()给求出最大值没有等等.

同理可以建立如下的双向通道:

main(){...}《-------------》float min(float a,float b){...}

main(){...}《-------------》float average(float a,float b){...}

这样,min()、average()也能返回信息到main(),

说白了,是我们希望被调用的函数能有信息反馈回主调函数中,即我们希望被调函数有返回值

下面的例子中,我们的主函数就收到了max()、min()、average()函数返回的数据,仔细看:

程序7:

/********************************************************/

#include〈stdio.h〉

float max(float a,float b)/*求任意2个数字的最大值。*/

{

return (a>b?a:b);

}

float min(float a,float b)/*求任意2个数字的最小值。*/

{

return (a<b?a:b);

}

float average(float a,float b)/*求任意2个数字的平均值。*/

{

return ((a+b)/2);

}


void main()

{

float a,b;

scanf("%f%f",&a,&b);

printf("max=%f/n",max(a,b));

printf("max=%f/n",min(a,b));

printf("max=%f/n",average(a,b));

}

程序7请对比程序6看吧。聪明的你一定能看出2点,

(1)、在max()、min()、average()函数中各有一个return;正是这个return语句将求出的值返回到调用处

(2)、void max(float a,float b)变成了float max(float a,float b).说明将可以为函数名赋一个float的数值。

仍然拿main()和max()间的调用为例,说明如下:

我们看到main()中有一条语句是:

printf("max=%f/n",max(a,b));

这条语句的执行过程如下:

(1)、首先执行其中的函数调用,即max(a,b),进入float max(float a,float b)中,如下:

float max(float a,float b)

(

return (a>b?a:b);

)

(2)、a>b?a:b就是求最大值,这个毫无疑问,

return (a>b?a:b)语句就将这个最大值的结果赋给函数名max,这样函数名max就代表最大值了.

(3)、max()执行完毕,返回到main()的函数调用处,最大值随同函数名max回到了main()中。

(4)、于是 printf("max=%f/n",max(a,b));就输出最大值了。

分享到:
评论

相关推荐

    精通WindowsAPI 函数 接口 编程实例

    第8章 服务 210 8.1 基本概念 210 8.1.1 服务控制器(SCM) 211 8.1.2 服务程序 211 8.1.3 服务控制管理程序 211 8.1.4 系统服务管理工具 211 8.1.5 服务的属性 211 8.2 编写服务程序 212 8.2.1 入口...

    精通Windows.API-函数、接口、编程实例.pdf

    第8章 服务 210 8.1 基本概念 210 8.1.1 服务控制器(SCM) 211 8.1.2 服务程序 211 8.1.3 服务控制管理程序 211 8.1.4 系统服务管理工具 211 8.1.5 服务的属性 211 8.2 编写服务程序 212 8.2.1 入口...

    PHP和MySQL WEB开发(第4版)

    第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免保存冗余数据 8.2.3 使用原子列值...

    PHP和MySQL Web开发第4版pdf以及源码

    第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免保存冗余数据 8.2.3 ...

    PHP和MySQL Web开发第4版

    第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免保存冗余数据 8.2.3 ...

    嵌入式实时操作系统small RTOS51原理及应用

    第8章 Small RTOS51的移植 8.1 系统相关的宏 8.2 与编译器无关的变量类型 8.3 OSStart() 8.4 OSIntCtxSw() 8.5 OS-TASK-SW() 8.6 OSTickISR() 8.7 OSIdle() 第9章 函数参考手册 9.1 OS-INT-ENTER()函数 9.2 ...

    寒江独钓-Windows内核安全编程(高清完整版).part4

    第8章 文件系统透明加密 223 8.1 文件透明加密的应用 224 8.1.1 防止企业信息泄密 224 8.1.2 文件透明加密防止企业信息泄密 224 8.1.3 文件透明加密软件的例子 225 8.2 区分进程 226 8.2.1 机密进程与普通进程 226 ...

Global site tag (gtag.js) - Google Analytics