不确定如何填充用户定义类型 records/elements

Not sure how user defined type records/elements are populated

在这段代码中,我不明白 LargeInt 类型的记录 IngLowerIngUpper 是如何填充的。例如,如果我将 udtFreeBytesAvail 添加到监视列表并在第 16 行设置断点 udtFreeBytesAvail 的记录将被填充,我知道这是因为API 函数 GetDiskFreeSpaceEx 的参数,但我不明白为什么两条记录都会被填充,而不是仅仅一条记录。以及为什么这两个记录具有不同的值。感谢您的帮助,如果我的问题没有得到很好的描述,我很抱歉,因为我是编程新手。

Public Type LargeInt
   lngLower As Long
   lngUpper As Long
End Type

Public Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias "GetDiskFreeSpaceExA" (ByVal   lpDirectoryName As String, lpFreeBytesAvailableToCaller As LargeInt, lpTotalNumberOfBytes As LargeInt, lpTotalNumberofFreeBytes As LargeInt) As Long

Public Function FreeDiskSpace(ByVal sDriveLetter As String) As Double

Dim udtFreeBytesAvail As LargeInt, udtTtlBytes As LargeInt
Dim udtTTlFree As LargeInt
Dim dblFreeSpace As Double

    If GetDiskFreeSpaceEx(sDriveLetter, udtFreeBytesAvail, udtTtlBytes, udtTTlFree) Then

            If udtFreeBytesAvail.lngLower < 0 Then
               dblFreeSpace = udtFreeBytesAvail.lngUpper * 2 ^ 32 + udtFreeBytesAvail.lngLower + 4294967296#
            Else
               dblFreeSpace = udtFreeBytesAvail.lngUpper * 2 ^ 32 + udtFreeBytesAvail.lngLower
            End If

    End If

FreeDiskSpace = dblFreeSpace

End Function

当您通过引用传递参数时(ByRef - 请注意它是 implicit default)然后在该过程中分配它...

Public Sub DoThing(ByRef value As Long)
    value = 42
End Sub

然后要调用该过程,您需要给它一个参数 - 如果您只是给它一个文字...

DoThing 10

...然后什么也没有发生,变量指针超出了范围。但是给它一个局部变量...

Dim local As Long
DoThing local

Debug.Print local

那应该输出 42.

这正是这里发生的事情,除了它不是局部变量,而是 UDT 成员 - T.S。简而言之:

GetDiskFreeSpaceEx populates it –


Public Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias "GetDiskFreeSpaceExA" ( _
    ByVal lpDirectoryName As String, _
    lpFreeBytesAvailableToCaller As LargeInt, _
    lpTotalNumberOfBytes As LargeInt, _
    lpTotalNumberofFreeBytes As LargeInt) As Long

函数本身 returns 一个 Long 整数,但 实际 输出是它采用的 ByRef 参数 - 注意 输入按值传递(ByVal)。


I don't understand why both records become populated, and not just one for example

假设 "records" 是关于 UDT 成员 lngLowerlngUpper 的,这实际上就是 UDT 所做的......你需要和他们一起玩一下,看看他们如何工作。尝试制作您自己的采用 UDT 的过程:

Public Sub DoThing(ByRef value As LargeInt)
    value.lngLower = 1
    value.lngUpper = 2
End Sub

API 函数的作用几乎完全相同 - 有两个值,因为 LargeInt 两个值。

其他人已经解释过了,但您似乎仍然难以理解为什么它有效,让我试着澄清一下:

UDT "keeps" 其成员(本例中为 2 个 Long 整数)在 连续 内存位置,lngUpper 的第一个字节紧跟在最后一个字节之后lngLower,共占用8字节(=64位)连续内存。 API GetDiskFreeSpaceEx 在作为 lpFreeBytesAvailableToCaller 等提供给它的变量的开头写入 64 连续 位。因此它 "fills out" UDT 的两个 32 位长变量。