There are several similar-looking statements in VB6: Let, Set, LSet, and RSet.
Let is used for assignment of general variables:
Copy the code code as follows:
[Let] varname = expression
In most cases, we omit Let and assign values directly with the equal sign, so many people don't even know the existence of Let.
Set is used for object assignment, pointing the variable to the object and increasing the object's reference count. Many people don't know what reference counting is.
So what is LSet used for? At first glance, it seems to be a combination of Let and Set, but it is not. The L in LSet is the abbreviation of Left, and its counterpart is RLet. You ask me how I know that L is the abbreviation of Left? What the document says:
Copy the code code as follows:
LSet Statement
Left aligns a string within a string variable, or copies a variable of one user-defined type to another variable of a different user-defined type.
RSet Statement
Right aligns a string within a string variable.
LSet has one more function than RSet. Let’s not look at this first. Let’s look at the same part first. Both are used to align a string to the left (right) in a string variable. What does it mean? In fact, I don’t understand it just by reading the documentation. Let’s test it in practice:
Copy the code code as follows:
Sub Main()
Dim url As String
Dim s As String
Let url = "//www.VeVB.COm"
s = String$(20, "*")
LSet s = url
Debug.Print s
RSet s = url
Debug.Print s
End Sub
Output (note the spaces):
Copy the code code as follows:
//www.VeVB.COm
//www.VeVB.COm
It is indeed left-aligned and right-aligned, and our asterisk * is replaced with a space. What is the use of this? In my opinion, it seems that it may be really useless. I don’t know what the designer thought.
However, another function of LSet is very powerful. It can copy a user-defined type variable to another user-defined type variable. What does this mean?
Let me give you an example. Do you know the IP address? The IP returned by pinging Baidu here is 61.135.169.125. The IP address in this format is only for human viewing. IP is actually represented by a 32-bit integer inside the computer. How to use VB to convert the IP address in the xxx.xxx.xxx.xxx format into a 32-bit integer? After some Google, you can write code similar to this:
Copy the code code as follows:
Sub Main()
Debug.Print IPToLong("61.135.169.125")
End Sub
Private Function IPToLong(IPStr As String) As Long
Dim Str() As String, HEXStr As String, TempStr As String
Dim x As Long
Str = Split(IPStr, ".")
HEXStr = ""
For x = 0 To UBound(Str)
TempStr = Hex(Str(x))
HEXStr = HEXStr & String(2 - Len(TempStr), "0") & TempStr
Next x
IPToLong = CLng("&H" & HEXStr)
End Function
The code works fine, there's nothing wrong with it, but we can write more "advanced" code using the LSet statement:
Copy the code code as follows:
Private Type myBytes
B1 As Byte
B2 As Byte
B3 As Byte
B4 As Byte
End Type
Private Type myLong
Val As Long
End Type
'By Demon
'http://VeVB.COm
Public Function IP2Long(ip As String) As Long
Dim a() As String
Dim b As myBytes
Dim l As myLong
a = Split(ip, ".")
'Note Little-Endian
b.B1 = CByte(a(3))
b.B2 = CByte(a(2))
b.B3 = CByte(a(1))
b.B4 = CByte(a(0))
LSet l = b
IP2Long = l.Val
End Function
Use LSet to copy a variable of type myBytes to a variable of type myLong. It is very good and powerful. Take a look at the generated assembly code:
Copy the code code as follows:
00401A0E lea eax, dword ptr [ebp-0x20]; address of variable b
00401A11 push eax
00401A12 lea eax, dword ptr [ebp-0x14]; address of variable l
00401A15 push eax
00401A16 push 0x4
00401A18 call __vbaCopyBytes ; jmp to MSVBVM60.__vbaCopyBytes
What is called is __vbaCopyBytes in MSVBVM60.DLL. The first parameter is the byte to be copied, the second parameter is the target address, and the third parameter is the source address. It is similar to the memcpy function in the C standard library, except that The order of parameters is different, and its internal implementation is nothing more than string transfer instructions in assembly:
Copy the code code as follows:
72A1A0F3 > mov ecx, dword ptr [esp+0x4]
72A1A0F7 push esi
72A1A0F8 mov esi, dword ptr [esp+0x10]
72A1A0FC push edi
72A1A0FD mov edi, dword ptr [esp+0x10]
72A1A101 mov eax,ecx
72A1A103 mov edx, edi
72A1A105 shrecx, 0x2
72A1A108 rep movs dword ptr es:[edi], dword ptr [esi]
72A1A10A mov ecx, eax
72A1A10C mov eax, edx
72A1A10E and ecx, 0x3
72A1A111 rep movs byte ptr es:[edi], byte ptr [esi]
72A1A113 popedi
72A1A114 pop esi
72A1A115 retn 0xC
It should be noted that the documentation warns us:
Copy the code code as follows:
Warning Using LSet to copy a variable of one user-defined type into a variable of a different user-defined type is not recommended. Copying data of one data type into space reserved for a different data type can cause unpredictable results.
When you copy a variable from one user-defined type to another, the binary data from one variable is copied into the memory space of the other, without regard for the data types specified for the elements.
Using LSet to copy user-defined type variables is not recommended and may lead to unexpected results (such as misaligned structures), so do not use the LSet statement unless you know what you are doing.