Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

re: procedure argments - setting referenc/pointer 1

Status
Not open for further replies.

wekkew

Programmer
Sep 28, 1998
123
GB
Hello
such a simple problem but it's driving me mad. Code is below, just need to set up pointer (gimme C...) to variable c passed into proc and then use than pointer (var2) to updated value. Have tried declaring things as objects, integer, using set, not using set, byref, not byref etc etc.

Before you suggest it I don't want to alter the global/local setup of variables as actual code is far more complex and larger than this and I don't want to have to rewrite the entire thing.

Thanks - Kate

Dim var2
Private Sub Command1_Click()
proc1
End Sub

Private Sub proc1()
Dim c As Integer
c = 99
proc2 c
Print "now in proc1 value of c is " & c 'should output 1
End Sub

Private Sub proc2(c)
Print "now in proc2 value of c is " & c 'should output 99
Set var2 = c
var2 = 1
End Sub
 
I can't try it right now, but did you try to declare proc2 this way:
Private Sub proc2(c As Variant)
var2 = c
End Sub
Maybe you should use "Set" in front of the second line. But I think it should work without that.
Why did you use var2 = 1. Maybe this is your problem you write c to var2 and then overwrite it with one.

Maybe you should write why it doesn't work. Is there an error message or just the wrong value in var2?
 
Private Sub proc2(c)
Print "now in proc2 value of c is " & c 'should output 99
c = 1
End Sub

Make sure that you do not use
Proc2 (variable)
because it evaluates variable as an expression, makes a copy and passes the copy ByRef i.e. changes will be made tyo the copy not "variable".
Call Proc2 (variable) ' is ok

Compare Code (Text)
Generate Sort in VB or VBScript
 
Dear Both
I'll deal with SamNickname's reply first

I can't try it right now, but did you try to declare proc2 this way:
Private Sub proc2(c As Variant)
var2 = c
End Sub
Maybe you should use "Set" in front of the second line. But I think it should work without that.

Yes - i've done both and neither work.

Why did you use var2 = 1. Maybe this is your problem you write c to var2 and then overwrite it with one.

I don't want var2 to hold the *contents* of c, i want it to hold the *address* of c so that any changes made to var2 will actually effect c. I have to do it this way becuase of the way the existing code is written.

Maybe you should write why it doesn't work. Is there an error message or just the wrong value in var2?

The wrong value appears when I print out c for the second time (proc1) - I get 99, it should be 1.


and now for JohnYingling's reply

Make sure that you do not use
Proc2 (variable)
because it evaluates variable as an expression, makes a copy and passes the copy ByRef i.e. changes will be made tyo the copy not "variable".
Call Proc2 (variable) ' is ok

John, I've done both of those, it still doesn't work. Also John, byref doesn't pass a copy, it passes the address, it's byVal that passes a copy - typing error methinks?

All I want to do is to put the address of c into var2 and then make a change to var2 which will ultimately effect the variable c.

This is so easy in C/C++ - just use pointers so how do I do the same thing in VB?
Kate

 
I never said ByRef passes a copy. I said, "it evaluates variable as an expression, makes a copy and passes the copy ByRef ". The language clearly indicates that the "copy" is made first and then that copy is passed ByRef.

It is standard language.
e.g. from the Docs
"If you specify a data type for an argument passed by reference, you must pass a value of that type for the argument. You can work around this by passing an expression, rather than a data type, for an argument. Visual Basic evaluates an expression and passes it as the required type if it can."

What is the difference between saying "argument passed by reference" and "passes a copy ByRef"?

I'm well aware of "passing addresses" as concerns ByRef but that language is rarely used in describing VB because "pointers" aren't part of the official language. You do not see "address" or "pointer" in the following from the Docs.
"Passing arguments by reference gives the procedure access to the actual variable contents in its memory address location. As a result, the variable's value can be permanently changed by the procedure to which it is passed. Passing by reference is the default in Visual Basic."

Try this to see the difference that parentheses make when used in a procedure call without "Call".

Dim I As integer
I = 2
Squareit I
Debug.Print I ' Prints 4
Squareit (I)
Debug.Print I ' Still prints 4
ChangeIt Sub (intI as Integer)
intI = intI * intI
End Sub
Compare Code (Text)
Generate Sort in VB or VBScript
 
Dear John
thank you for your comprehensive explanation - I agree with everything you've said - but I stil can't get the original code to work!!!!!!

roll on vb.net...

Kate
 
Option Explicit
Private Declare Sub RtlMoveMemory Lib "kernel32" ( _
ByVal DestPtr As Long, ByVal SourcePtr As Long, _
ByVal Bytes As Long)

Public var2 As Long

Private Sub Command1_Click()
proc1
End Sub

Private Sub proc1()
Dim c As Integer
c = 99
Call proc2(c)
Print "now in proc1 value of c is " & c 'should output 1
End Sub

Private Sub proc2(ByRef c As Integer)
Print "now in proc2 value of c is " & c 'should output 99
var2 = VarPtr(c)
varset var2, 4
End Sub

Public Sub varset(ByVal Dest As Long, ByVal Source As Integer)
RtlMoveMemory Dest, VarPtr(Source), LenB(Source)
End Sub
 
Dear StrongM

Thank you so much - I can't belive you have to go through all that hassle just to copy a memory location!!

This is why I love C....

Thanks again!
Kate
 
Encapsulate your variable(*) in a TYPE structure and use LSET to overlay that structure:

Public Type t_intMyInteger
c As Integer
End Type

Public Sub main()
proc1
End Sub

Private Sub proc1()
Dim intHelp As t_intMyInteger
With intHelp
.c = 99
proc2 intHelp
Debug.Print "now in proc1, value of c is " & .c
End With
End Sub

Private Sub proc2(intHelp As t_intMyInteger)
Debug.Print "now in proc2, value of c is " & intHelp.c
Dim intVar2 As t_intMyInteger
'Modify Variable2
intVar2.c = 1
'Copy modified variable into procedure argument
LSet intHelp = intVar2
End Sub


(*) A string variable can be overlaid without using a structure. cfr: LSET statement in Reference Guide.

Be careful to match variable types exactly when using overlays ( or CopyMemory) _________________________________
In theory, there is no difference between theory and practice. In practice, there is. [attributed to Yogi Berra]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top