按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗

时间:2022-09-23 18:13:03
vb6.0中按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗?为什么?

21 个解决方案

#1


等效与否这个的具体问题具体分析
就两者而言,含义是不同的,Byval是传值,也就是传递变量的一个副本;而Byref是传引用,也就是把地址传过去。

#2


最好能分别讨论这个变量为long类型和string类型时的情况

#3


假设这个变量叫X,是long类型
①byval x 时,vb会自动创建X的替身x1,然后将x1的地址返回给实参(完成外部变量与函数内部变量的对接,类似“索引”),函数对实参的操作实际是对x1的操作,x本身没有变化。
②byref x 时,vb会直接将x的地址返回给实参,函数对实参的操作实际是对x本身的操作。

请问上面两条推论成立吗?

#4


vb6.0中按byval方式传递一个变量的地址:错误,传递是值
按byref传递才是变量的地址

函数或过程的参数传递需要通过栈,栈是函数调用者和函数内部能够知道的内存地址,是一种调用约定,调用者和被调用者能够准确的理解每个栈内存属于哪个变量。
调用的时候,ByVal则将对应的参数值复制到某个栈内存;ByRef的时候,则将该变量的地址复制到栈内存

#5


以下摘自MSDN
Byval
按值
一种将参数值而不是将地址传递给过程的方式,这就使过程访问到变量的复本。结果,过程不可改变变量的真正值。


Byref
按地址
一种将参数地址而不是将值传递给过程的方式,这就使过程访问到实际的变量。结果,过程可改变变量的真正值。除非另作说明,否则按地址传递参数。

#6


worldy
我们的理解似乎有些误差。我的意思是
vb6.0中按byval方式传递一个“变量的地址”
“变量的地址”本身也是一个变量(可以想成是一个临时变量)假设为a,a代表了那个变量的地址,可以用取地址函数取到值赋值给a。

#7


worldy你好

“函数或过程的参数传递需要通过栈...”
是怎么理解的,能不能分享下

#8


引用楼主 jgxzjf2012 的回复:
vb6.0中按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗?为什么?

等不等效,没那么简单!看你怎么用了。比如:在ActiveX DLL中,如果DLL有一个参数声明成ByRef,则这个参数是可以返回值给调用DLL的主程序的;如果这个参数声明成ByVal,则不能返回值给主程序。
API函数VarPtr是返回变量的地址,为了获取字符串的指针,而非保存字符串的变量的指针,只须在变量名前加上ByVal即可:VarPtr(ByVal S)(相当于StrPtr(S),但不等于VarPtr(S))。
举个例子:
Dim S As String
S = "CSDN"
Debug.Print VarPtr(S), VarPtr(ByVal S), StrPtr(S) '在我的电脑里面结果分别为1307680、1847644、1847644
这里有个详细例子,看完之后就明白了: http://topic.csdn.net/u/20090901/09/dddf35aa-7838-4415-85b2-222358422d81.html

#9


引用 6 楼 jgxzjf2012 的回复:
worldy
我们的理解似乎有些误差。我的意思是
vb6.0中按byval方式传递一个“变量的地址”
“变量的地址”本身也是一个变量(可以想成是一个临时变量)假设为a,a代表了那个变量的地址,可以用取地址函数取到值赋值给a。


你的意思是以Byval方式来传递一个地址,比如通过VarPtr获得地址传递?如果是这样
VB的自定义函数肯定不等效,因为被调用者(函数或过程)在编译的时候,是按照定义时候按值或者按地址编译的,调用者如果使用ByVal 或者Byref修改调用的参数,对于内部函数将会出现编译错误。

API调用,byval的声明参数,一般是不可以使用Byref进行强制
但是Byref声明的参数,在一些时候可以使用ByVal进行强制,比如你先获得Varptr

不知道说的对不对

#10


说了一堆... 
都什么啊.......

对lz问题的回答: 等效 ...

因为vb这种高级语言,掩盖的东西太多了,导致看起来似乎不一样,其实是一样的
按照lz说的方法传过去后,参数都是一样的值, 只不过必须通过特殊方法来证明,

比如 byval 的直接 msgbox 参数, byref的 copymemory a,参数,4 然后再 msgbox a
如果相等就说明等效了, 其实根本就是等效的, 上面那些说了一堆的都没用, 只会让人越看越迷糊

#11


PctGL
可不可以说的再详细点

#12


PctGL
copymemory的第二个参数(设为变量b),copymemory函数内部用到的是b的内存地址,而不是b的值,是吗?感觉这里面被VB代劳的工作特别多,认识比较吃力

#13


PctGL
设:
一个Long型变量为A,其内存地址ad=108,其va=1008。
那么:
任何一个使用他作为参数的函数(如:msgbox、copymenory...),无非使用以下两种方式传参。
①byval方式②byref方式
例01:msgbox byref A
     msgbox byval A.ad
例02:copymemory x,byref A,4
     copymemory x,byval A.ad,4
例...
我的问题是:这两种方式执行的结果相同吗?为什么?

#14


弄的跟说书是的...

模块里面写这些东西:

private 变量1 as long

sub TestByval(byval a as long)
  msgbox a
end sub

sub TestByref( a as long)
  
   dim m as long 
   copymemory m,a,4
   msgbox m
end sub


调用:
testbyval varptr(变量1)
testbyref 变量1

#15


改个

Sub TestByref(a As Long)
  
  Dim m As Long
  copymemory m, VarPtr(a), 4
  MsgBox m
End Sub

#16


pctgl
你把问题复杂了,而且你的命题和我想要的结论,推论关系不明确

#17


①函数相同,分别代入以下参数
byref A
byval A.ad
②结果相同则证明成立,否则就不对
③为什么?

#18


真正理解透这个问题必须:
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

#19


问题最新思考
前提:
一个完整变量包含两方面内容①内存地址②值。
假设有这样一个变量A,其内存地址为A.adr,其值为A.val
那么当A作为参数传递进一个函数时可采用哪些方式?
答:byref[vb默认方式]、byval
具体思考见图:
按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗

#20


图:
按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗

#21


“vb6.0中按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗?为什么?” 
 
byval、byref代表两种参数传递方式,本身不是函数,无法决定传递好的参数做什么用。参数的作用是由过程中的代码来决定的。如果把参数比作一块毛巾,如果我用它来洗脸就是脸布,用它来擦桌子就是抹布,要看过程是怎样使用它的,所以以上问题可以回答是等效的,也可以回答是不等效的,原因不在byval与byref,而在于我们在写这个过程代码时,是想怎样驾驭他们为我所用的。

#1


等效与否这个的具体问题具体分析
就两者而言,含义是不同的,Byval是传值,也就是传递变量的一个副本;而Byref是传引用,也就是把地址传过去。

#2


最好能分别讨论这个变量为long类型和string类型时的情况

#3


假设这个变量叫X,是long类型
①byval x 时,vb会自动创建X的替身x1,然后将x1的地址返回给实参(完成外部变量与函数内部变量的对接,类似“索引”),函数对实参的操作实际是对x1的操作,x本身没有变化。
②byref x 时,vb会直接将x的地址返回给实参,函数对实参的操作实际是对x本身的操作。

请问上面两条推论成立吗?

#4


vb6.0中按byval方式传递一个变量的地址:错误,传递是值
按byref传递才是变量的地址

函数或过程的参数传递需要通过栈,栈是函数调用者和函数内部能够知道的内存地址,是一种调用约定,调用者和被调用者能够准确的理解每个栈内存属于哪个变量。
调用的时候,ByVal则将对应的参数值复制到某个栈内存;ByRef的时候,则将该变量的地址复制到栈内存

#5


以下摘自MSDN
Byval
按值
一种将参数值而不是将地址传递给过程的方式,这就使过程访问到变量的复本。结果,过程不可改变变量的真正值。


Byref
按地址
一种将参数地址而不是将值传递给过程的方式,这就使过程访问到实际的变量。结果,过程可改变变量的真正值。除非另作说明,否则按地址传递参数。

#6


worldy
我们的理解似乎有些误差。我的意思是
vb6.0中按byval方式传递一个“变量的地址”
“变量的地址”本身也是一个变量(可以想成是一个临时变量)假设为a,a代表了那个变量的地址,可以用取地址函数取到值赋值给a。

#7


worldy你好

“函数或过程的参数传递需要通过栈...”
是怎么理解的,能不能分享下

#8


引用楼主 jgxzjf2012 的回复:
vb6.0中按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗?为什么?

等不等效,没那么简单!看你怎么用了。比如:在ActiveX DLL中,如果DLL有一个参数声明成ByRef,则这个参数是可以返回值给调用DLL的主程序的;如果这个参数声明成ByVal,则不能返回值给主程序。
API函数VarPtr是返回变量的地址,为了获取字符串的指针,而非保存字符串的变量的指针,只须在变量名前加上ByVal即可:VarPtr(ByVal S)(相当于StrPtr(S),但不等于VarPtr(S))。
举个例子:
Dim S As String
S = "CSDN"
Debug.Print VarPtr(S), VarPtr(ByVal S), StrPtr(S) '在我的电脑里面结果分别为1307680、1847644、1847644
这里有个详细例子,看完之后就明白了: http://topic.csdn.net/u/20090901/09/dddf35aa-7838-4415-85b2-222358422d81.html

#9


引用 6 楼 jgxzjf2012 的回复:
worldy
我们的理解似乎有些误差。我的意思是
vb6.0中按byval方式传递一个“变量的地址”
“变量的地址”本身也是一个变量(可以想成是一个临时变量)假设为a,a代表了那个变量的地址,可以用取地址函数取到值赋值给a。


你的意思是以Byval方式来传递一个地址,比如通过VarPtr获得地址传递?如果是这样
VB的自定义函数肯定不等效,因为被调用者(函数或过程)在编译的时候,是按照定义时候按值或者按地址编译的,调用者如果使用ByVal 或者Byref修改调用的参数,对于内部函数将会出现编译错误。

API调用,byval的声明参数,一般是不可以使用Byref进行强制
但是Byref声明的参数,在一些时候可以使用ByVal进行强制,比如你先获得Varptr

不知道说的对不对

#10


说了一堆... 
都什么啊.......

对lz问题的回答: 等效 ...

因为vb这种高级语言,掩盖的东西太多了,导致看起来似乎不一样,其实是一样的
按照lz说的方法传过去后,参数都是一样的值, 只不过必须通过特殊方法来证明,

比如 byval 的直接 msgbox 参数, byref的 copymemory a,参数,4 然后再 msgbox a
如果相等就说明等效了, 其实根本就是等效的, 上面那些说了一堆的都没用, 只会让人越看越迷糊

#11


PctGL
可不可以说的再详细点

#12


PctGL
copymemory的第二个参数(设为变量b),copymemory函数内部用到的是b的内存地址,而不是b的值,是吗?感觉这里面被VB代劳的工作特别多,认识比较吃力

#13


PctGL
设:
一个Long型变量为A,其内存地址ad=108,其va=1008。
那么:
任何一个使用他作为参数的函数(如:msgbox、copymenory...),无非使用以下两种方式传参。
①byval方式②byref方式
例01:msgbox byref A
     msgbox byval A.ad
例02:copymemory x,byref A,4
     copymemory x,byval A.ad,4
例...
我的问题是:这两种方式执行的结果相同吗?为什么?

#14


弄的跟说书是的...

模块里面写这些东西:

private 变量1 as long

sub TestByval(byval a as long)
  msgbox a
end sub

sub TestByref( a as long)
  
   dim m as long 
   copymemory m,a,4
   msgbox m
end sub


调用:
testbyval varptr(变量1)
testbyref 变量1

#15


改个

Sub TestByref(a As Long)
  
  Dim m As Long
  copymemory m, VarPtr(a), 4
  MsgBox m
End Sub

#16


pctgl
你把问题复杂了,而且你的命题和我想要的结论,推论关系不明确

#17


①函数相同,分别代入以下参数
byref A
byval A.ad
②结果相同则证明成立,否则就不对
③为什么?

#18


真正理解透这个问题必须:
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

#19


问题最新思考
前提:
一个完整变量包含两方面内容①内存地址②值。
假设有这样一个变量A,其内存地址为A.adr,其值为A.val
那么当A作为参数传递进一个函数时可采用哪些方式?
答:byref[vb默认方式]、byval
具体思考见图:
按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗

#20


图:
按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗

#21


“vb6.0中按byval方式传递一个变量的地址与按byref传递这个变量本身等效吗?为什么?” 
 
byval、byref代表两种参数传递方式,本身不是函数,无法决定传递好的参数做什么用。参数的作用是由过程中的代码来决定的。如果把参数比作一块毛巾,如果我用它来洗脸就是脸布,用它来擦桌子就是抹布,要看过程是怎样使用它的,所以以上问题可以回答是等效的,也可以回答是不等效的,原因不在byval与byref,而在于我们在写这个过程代码时,是想怎样驾驭他们为我所用的。