Office中国论坛/Access中国论坛

标题: 【新手入门】之五:公共变量与传址过程、传值过程 [打印本页]

作者: roych    时间: 2012-9-23 02:29
标题: 【新手入门】之五:公共变量与传址过程、传值过程
在百度里见到一道很有意思的编程题,先贴上两段代码代码给大家练练:
第一段代码:返回值是什么?

  1. Dim a As Integer
  2. Sub test()
  3.     Dim b As Integer
  4.     a = 1
  5.     b = 2
  6.     Debug.Print fun1(fun1(a, b), b)
  7.     Debug.Print a
  8.     Debug.Print b
  9. End Sub
  10. Function fun1(x As Integer, y As Integer) As Integer
  11.     Dim i As Integer
  12.     For i = 1 To y
  13.         y = y + 1
  14.         x = x + 1
  15.         a = x + y
  16.     Next i
  17.     fun1 = a + y
  18. End Function
复制代码

第二段代码:和上面的代码相比,只是加了“ByVal”关键字,返回结果还是一样吗?

  1. Dim a As Integer
  2. Sub test()
  3.     Dim b As Integer
  4.     a = 1
  5.     b = 2
  6.     Debug.Print fun1(fun1(a, b), b)
  7.     Debug.Print a
  8.     Debug.Print b
  9. End Sub
  10. Function fun1(ByVal x As Integer, ByVal y As Integer) As Integer
  11.     Dim i As Integer
  12.     For i = 1 To y
  13.         y = y + 1
  14.         x = x + 1
  15.         a = x + y
  16.     Next i
  17.     fun1 = a + y
  18. End Function
复制代码


公共变量的影响:
问题3:对第一段代码删除 Dim a As Integer,并把参数(x As Integer, y As Integer)改为:(x,y)【注】会有怎样的结果呢?
问题4:对于第二段代码同样删除这句公共变量,又会有怎样的结果呢?

答案嘛,大家可以在模块的立即窗口(Ctrl+G)中得到,实在不清楚的再问我。为什么会这样。由于时间关系,我得稍后一些时间才能回复了,先占个楼层。
【注:由于删除公共变量,x,y均为缺省变量类型Variant。如果仍保留子函数中的Integer类型,则会在传址过程中出现变量不匹配的编译错误,因而需要改为(x,y)】
【新手入门】之一:If分支语句
【新手入门】之二:分支语句总结
【新手入门】之三:循环语句For
【新手入门】之四:循环语句Do和死循环
【新手入门】之五:公共变量与传址过程、传值过程
【新手入门】之六:“悲欢离合总无情”——浅谈Split和Join
【新手入门】之七:嵌套与并列——再谈If流程问题
【新手入门】之八:“连就连”——浅谈“&”和“+”连接符的区别

【新手入门】之九:从百钱百鸡谈起——浅谈“规划求解”兼答lingjiang问
【新手入门】之十:书到用时方恨少——自定义菜单(Access 2003)的制作
【新手入门】之十一:浅谈ADO之序言
【新手入门】之十二:浅谈ADO之Connection
【新手入门】之十三:浅谈ADO之Conmmand(上)
【新手入门】之十四:浅谈ADO之Command(下)
【新手入门】之十五:浅谈ADO之Recordset(上)
【新手入门】之十六:浅谈ADO之Recordset(下)
【新手入门】之十七:浅谈列表框的使用
【新手入门】之十八:双击列表框修改数据
【新手入门】之十九:从“书与女友恕不外借”谈起——浅谈“Bookmark”的使用
【新手入门】之二十:“书与书签”——bookmark属性答疑
【新手入门】之二十一:记录集的“凌迟”——逐条导出记录集

【新手进阶】之一:基础算法(一)
【新手进阶】之二:基础算法(二)
【新手进阶】之三:基础算法(三)
【新手进阶】之四:基础算法(四)
【新手进阶】之五:排序搜索(一)
【新手进阶】之六:排序搜索(二)
【新手进阶】之七:递归算法
【新手进阶】之八:冒泡排序
【新手进阶】之九:浅谈不绑定数据源操作记录
【新手进阶】之十:工作日的计算
【新手进阶】之十一:“庖丁解牛”和“纪昌学射”——浅谈表格式文本数据的导入
【新手进阶】之十二:从四脚腾空的奔马谈起——原来界面可以这样设计
【新手进阶】之十三:Outlook风格导航界面
【新手进阶】之十四:仓库管理系统
作者: roych    时间: 2012-9-23 02:29
本帖最后由 roych 于 2012-9-23 21:27 编辑

问题3:
取消公共变量之后,实际上嵌套函数已经发生很大变化的了。具体过程是:
第1次传址过程,没什么好说的,x=a+1=2,y=b+1=3,a=x+y=5
第2次传址过程,x=x+1=2+1=3,y=y+1=3+1=4,a=x+y=7。
从上面来看,实际上第2次传址过程并没有把a=5传递给fun1,而是继续进行循环内运算的(这和定义公共变量是完全不同的),换句话说,fun1(a,b)=a+y=7+4=11(这时候x=3,y=4)。

因此:fun1(fun1(a,b),b)=fun1(11,4),这样一来,那么显然循环就得执行4次了。
第1次:x=11+1=12,y=4+1=5,a=12+5=17
第2次:x=12+1=13,y=5+1=6,a=13+6=19
第3次:x=13+1=14,y=6+1=7,a=12+5=21
第4次:x=14+1=15,y=7+1=8,a=13+6=23
那么fun1(fun1(a,b),b)=fun1(11,4)=a+y=23+8=31。
因此得到的结果,显然是31,3,8【为什么是3,而不是15?以x才是15,a一直停留在嵌套内的循环里,即x=x+1+1=3。也就是说,嵌套前a已经定型了~~】
*************************************************************************************************
问题4:
事实上这和之前的解释没太大不同。过程如下:
第1次:x=a+1=2,y=b+1=3,a=x+y=5
第2次:x=x+1=2+1=3,y=y+1=3+1=4,a=x+y=7 fun1(a,b)=7+4=11。
而我们前面说过,传值过程,传递完之后,那个值是不会发生变化的。因此,外循环也只是循环2次。即:fun1(fun1(a,b),b)=fun1(11,2)
第1次:x=11+1=12,y=2+1=3,a=x+y=15
第2次:x=12+1=13,y=3+1=4,a=x+y=17
fun1(fun1(a,b),b)=fun1(11,2)=a+y=17+4=21。
b肯定是不变的2了,那么取消公共变量后的a呢?
不用猜了,取消公共变量后,传值完之后,变量便回复到初始值了,也就是a=1。会感到意外吗?

啰啰嗦嗦地讲这么多,也不知道会不会有人觉得,这些代码到底有没有实际用途呢?事实上,曾经为一个同事写过一段ADO的代码,他问了一个很专业的问题,为什么在Update记录集后,非要加上一句a=0呢?如果他了解传值过程和传址过程就很清楚原因了:加上这句后才能初始化数据啊。
作者: yanwei82123300    时间: 2012-9-23 13:47
thanks you sharing it
作者: yanghua1900363    时间: 2012-9-23 14:38
学习学习

作者: lynnwang    时间: 2012-9-23 15:43
正好,我这里也有一个,更有意思的!{:soso_e104:}

Sub testFuns()
Dim lngRet As Long, varLong As Long
varLong = 1
fun1 varLong
Debug.Print varLong

varLong = 1
fun1 (varLong)
Debug.Print varLong

varLong = 1
Call fun1(varLong)
Debug.Print varLong
End Sub
Function fun1(ByRef lng As Long) As Integer
lng = 1000
End Function


作者: lynnwang    时间: 2012-9-23 15:44
输出:
1000
1
1000

谁知道呢?{:soso_e128:}
作者: lynnwang    时间: 2012-9-23 15:50
同样给出SUB。

Sub testSubs()
Dim lngRet As Long, varLong As Long
varLong = 1
sub1 varLong
Debug.Print varLong

varLong = 1
sub1 (varLong)
Debug.Print varLong

varLong = 1
Call sub1(varLong)
Debug.Print varLong

varLong = 1
Call sub1(lng:=varLong)
Debug.Print varLong

varLong = 1
sub1 lng:=varLong
Debug.Print varLong
End Sub
Sub sub1(ByRef lng As Long)
lng = 1000
End Sub

大家慢慢找答案吧{:soso_e113:}
作者: roych    时间: 2012-9-23 21:37
lynnwang 发表于 2012-9-23 15:43
正好,我这里也有一个,更有意思的!

Sub testFuns()

有点意思,哈哈~~~可以加深大家对传址过程的理解。
作者: t小宝    时间: 2012-9-23 21:46
看了头会晕,我还是不看了
作者: ycxchen    时间: 2012-9-24 20:38
本帖最后由 ycxchen 于 2012-9-24 20:39 编辑

很长时间不见版主有“新手进阶”东西了,我要学习!
作者: lynnwang    时间: 2012-9-25 00:39
我们一般会在下面第二个容易掉进陷井!

Sub testFuns()
    Dim lngRet As Long, varLong As Long
    varLong = 1
    fun1 varLong
    Debug.Print varLong

    varLong = 1
    fun1 (varLong)
    Debug.Print varLong

    varLong = 1
    Call fun1(varLong)
    Debug.Print varLong
   
    varLong = 1
    Call fun1((varLong))
    Debug.Print varLong
   
    varLong = 1
    Call fun1(lng:=varLong)
    Debug.Print varLong

    varLong = 1
    Call fun1(lng:=(varLong))
    Debug.Print varLong
End Sub

Function fun1(ByRef lng As Long) As Integer
    lng = 1000
End Function

输出得到:

1000
1
1000
1
1000
1

应该都看出来了吧,答案:
不管[Sub][Function],如果对参数变量加了括号,即使过程参数是传址,也会将参数作为传值(参数复本传入过程)
如果还不理解,将fun1改为两个参数(其他稍作修改)再运行,你就会彻底明白

Function fun1(ByRef lng As Long,lng2 As Long) As Integer
    lng = 1000
    lng2=2000
End Function

作者: 咱家是猫    时间: 2012-9-25 09:43
真的新手肯定早吓跑了.
作者: zhuyiwen    时间: 2012-9-25 10:04
lynnwang 发表于 2012-9-25 00:39
不管[Sub][Function],如果对参数变量加了括号,即使过程参数是传址,也会将参数作为传值(参数复本传入过程)


为什么?
作者: zhuyiwen    时间: 2012-9-25 10:21
推演
参数定义
function x(var as integer)  = function x(byref var as integer)

变量和表达式
传递参数时
  1. dim k
  2. dim a as integer
  3. k = x(a)    ' 传址,即传的变量的地址,函数内部可以影响 a 的值
复制代码
如果抛弃函数的返回值,VBA 要求如此书写
  1. x a    ' 同样传址,函数内部可以影响 a 的值
复制代码
(a) = (a + 0) ' 就 a 数值类型而言
因此 (a) 是表达式,它返回的另一个地址空间中的值,而不是 a 变量地址空间中的值

故:
  1. k = x((a)) ' 此时传递的不是 a 的地址,而是表达式 (a) 的地址,此时,函数内部影响的是表达式 (a) 地址空间中的,而不是 a 的值
复制代码
如果抛弃函数返回值,VBA 应该这样写
  1. x (a)
复制代码

作者: lynnwang    时间: 2012-9-25 22:08
还是老朱,牛叉,见多识广,分析到点了。

()=传值=值的复本
作者: renyucai1963    时间: 2012-9-26 04:01
学习。
作者: yori2007    时间: 2012-10-6 22:09

作者: tmtming    时间: 2012-10-13 12:46
好好学习.
作者: 微微森林    时间: 2013-3-28 20:49
系统性学完。
作者: 5574916    时间: 2013-6-27 18:40
学习学习,谢谢分享!
作者: wen123456    时间: 2013-9-22 13:52
新手上路
作者: msyangyi    时间: 2014-5-26 14:18
对对答案
作者: msyangyi    时间: 2014-5-26 14:43
恩,真的很好
作者: zpy2    时间: 2014-6-23 06:46
不错,在类里用,传值,传址大不一样!!
作者: 桑松木    时间: 2015-1-10 19:36
我在学习
作者: 山东小妮子    时间: 2015-2-1 21:16
学习
作者: tiantianiec    时间: 2015-2-2 17:00
aaaaaaaaaaaaa
作者: kililyl    时间: 2015-4-7 03:12
很多年前学过,现在又忘了,多年没有搞编程了,现在又要捡起来了
作者: 轻风    时间: 2015-8-21 11:50
{:soso_e100:}
作者: songgpljh    时间: 2015-10-10 16:19
学习一下
作者: cshiq    时间: 2016-1-17 05:49
公共变量与传址过程、传值过程
作者: socar_bbman    时间: 2016-2-22 01:55
看代码学习
作者: Superleistung    时间: 2016-4-15 15:05
有涉及到模块公共变量值的传递吗?想学习下
作者: 神经挺住    时间: 2016-4-15 17:28
学习
作者: 鄱湖人2012    时间: 2016-5-6 20:08
学习
作者: 山之冬    时间: 2016-7-1 13:06
学习
作者: zshining    时间: 2016-7-4 15:59
楼主的好东西,小白来学习了
作者: gzhxhy    时间: 2016-7-21 16:18
赞一个
作者: yhl091122    时间: 2016-8-19 14:05
学习
作者: wind7412    时间: 2016-9-10 08:15
学习一下
作者: p51218    时间: 2016-9-14 00:14
哈哈哈
作者: czwziy    时间: 2016-12-11 00:04
回复学习
作者: su_xx    时间: 2016-12-14 09:28
学习学习
作者: 寒月TEA    时间: 2017-1-23 12:46
感谢分享
作者: 72310    时间: 2017-2-23 14:00
新手回复
作者: guan818355    时间: 2017-3-12 21:21
fenxiang
作者: busyboy    时间: 2017-3-13 15:31
新手一个,学习
作者: 農民工    时间: 2017-4-24 08:30
学习
作者: hongyepiaofei    时间: 2017-5-19 17:04
学习一下,谢谢
作者: 双木无神    时间: 2017-6-26 10:59
好好学习
作者: ztaccess    时间: 2017-8-7 05:10
感谢大神指导
作者: ztaccess    时间: 2017-8-7 05:10
感谢大神指导,谢谢无私分享
作者: ztaccess    时间: 2017-8-7 05:11
祝论坛越办越好,感谢楼主热心分享
作者: ztaccess    时间: 2017-8-7 05:12
感谢楼主热心分享都是好贴
作者: 亚洲雄风    时间: 2017-11-15 17:28
好东东啊……。
作者: zimohong    时间: 2017-12-22 16:52
好东西,多谢了啊
作者: pfrs01    时间: 2017-12-25 15:25
学习了,多谢
作者: secseasun    时间: 2018-5-3 14:52
感谢分享、
作者: ej1213    时间: 2018-6-8 16:35
谢谢1
作者: 六月雪    时间: 2018-8-11 18:31
哦哦哦哦哦哦哦哦哦
作者: gaofei186    时间: 2018-8-20 14:00
看看一下
作者: hxx3970    时间: 2018-9-12 11:56
学习了
作者: 1271650489    时间: 2020-4-17 09:28
学习一下
作者: youdm    时间: 2021-3-16 20:37
感谢分享,向您学习!
作者: 付谦    时间: 2021-5-31 08:22
学习




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3