Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the result of VarPtr(ByVal str) the same as StrPtr(str) ? (VB6)

Tags:

vb6

In VB6 VarPtr should return the address of the variable, in this case the address of the variable str which is allocated on stack, and holds a pointer to a string in memory. StrPtr (or StrPtr) should return the address of the allocated string in the memory. ByVal should just create a copy, but in this case, it works strangely:

Dim str As String
str = "asd"
Debug.Print VarPtr(str)
Debug.Print VarPtr(ByVal str)
Debug.Print StrPtr(str)

The result is:

1636452 
110882980 
110882980 

Why is the result of VarPtr(ByVal str) the same as StrPtr(str) ?

like image 878
Iter Ator Avatar asked Nov 26 '17 18:11

Iter Ator


1 Answers

Strings passed ByVal pass the address of the first character of the containing C string in the BStr. StrPtr does the same.

There are two reasons that spring to mind for doing this. Passing Unicode to API calls and string building.

Passing Unicode to API calls

You could use StrPtr on a string rather than a byte array when sending Unicode strings to API functions.

Dim ByteArr() as Byte
Var1="My Text"
ByteArr = Var1
APICall(ByteArr(0))
APICall(StrPtr(Var1))

Should both pass a Unicode string to an API functions. Unicode strings are converted to ANSI strings when using the declare statement as Win 95 didn't do unicode.

String Building

On the other hand if you are string building, then that is built in to VBA using the Left, Right, and Mid statements, not functions (they are overloaded).

Sub Main()
    Dim Var As String
    Var = "gggggggggggg"
    MsgBox StrPtr(Var)
    Mid(Var, 1, 2) = "xx"
    MsgBox StrPtr(Var) & " - " & Var
End Sub

ByVal Versus ByRef

Some authors like to say that the ByVal keyword is overloaded for strings, meaning that it takes on a different meaning when applied to strings than when applied to other variables. Frankly, I don't see it. Writing:

ByVal str As String 

tells VB to pass the contents of the BSTR (actually the ABSTR), which is the pointer to the character array. Thus, ByVal is acting normally--it just happens that the content of the BSTR is a pointer to another object, so this simulates a pass by reference. Similarly:

ByRef str As String

passes the address of the BSTR, as expected.

Win32 API Programming with Visual Basic, Chapter 6 Strings, O'Reilly, from MSDN Library October 2001

StrPtr

Strings in Visual Basic are stored as BSTR's. If you use the VarPtr on a variable of type String, you will get the address of the BSTR, which is a pointer to a pointer of the string. To get the address of the string buffer itself, you need to use the StrPtr function. This function returns the address of the first character of the string. Take into account that Strings are stored as UNICODE in Visual Basic.

To get the address of the first character of a String, pass the String variable to the StrPtr function.

Example:

Dim lngCharAddress as Long
Dim strMyVariable as String
strMyVariable = "Some String"
lngCharAddress = StrPtr(strMyVariable) 

You can use this function when you need to pass a pointer to a UNIOCODE string to an API call.

HOWTO: Get the Address of Variables in Visual Basic Q199824 Microsoft Knowledge Base, MSDN October 2001.

VarPtr is not part of the VBA/VB6 language, therefore companies that implement VBA (like Corel) may not implement it in their VBA. The VBA spec is here https://msdn.microsoft.com/en-us/library/dd361851.aspx

like image 170
ACatInLove Avatar answered Oct 16 '22 06:10

ACatInLove