Не уверен, как заполняются пользовательские записи типа / элементы - PullRequest
0 голосов
/ 12 марта 2020

В этом коде я не понимаю, как заполняются записи IngLower и IngUpper типа LargeInt. Например, если я добавлю 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

Ответы [ 2 ]

2 голосов
/ 16 марта 2020

Другие уже объяснили это, но, поскольку вы все еще, кажется, изо всех сил пытаетесь понять , почему это работает, позвольте мне попытаться уточнить это:

UDT "держит" своих членов (2 Длинные целые числа в этом случае) в последовательных ячейках памяти, 1-й байт lngUpper непосредственно следует за последним байтом lngLower, занимая в общей сложности 8 байтов (= 64 бита) последовательных памяти. API GetDiskFreeSpaceEx записывает 64 последовательных битов в начале переменных, предоставленных ему как lpFreeBytesAvailableToCaller et c. Следовательно, он «заполняет» обе 32-битные переменные Long UDT.

2 голосов
/ 12 марта 2020

Когда вы передаете параметр по ссылке (ByRef - обратите внимание, что это неявное значение по умолчанию ), а затем назначаете его в этой процедуре ...

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

Затем вызывать этой процедуре вам нужно дать ей аргумент - если вы просто дадите ей литерал ...

DoThing 10

... тогда ничего не произойдет, указатель переменной просто выпадет из области видимости. Но дайте ему локальную переменную ...

Dim local As Long
DoThing local

Debug.Print local

И это должно вывести 42.

Это именно то, что здесь происходит, за исключением того, что вместо локальной переменной это UDT член - TS изложил это кратко:

GetDiskFreeSpaceEx заполняет это - TS 8 минут go


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

Сама функция возвращает Long целое число, но вывод real - это ByRef параметров, которые она принимает - обратите внимание, что входные данные передаются по значению (ByVal).


Я не понимаю, почему обе записи заполняются, а не только одна, например

Предполагая, что "записи" относятся к UDT члены lngLower и lngUpper, это действительно то, что делает UDT ... Вам нужно немного поиграть с ними, посмотреть, как они работают. Попробуйте создать свою собственную процедуру, которая принимает UDT:

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

Функция API делает в точности то же самое - есть два значения, потому что LargeInt - это два значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...