Декларирует определяемый пользователем тип.
Type используется для объявления пользовательских типов данных,
содержащие одно или несколько полей данных, в том числе целые типы, типы с
плавающей точкой, массивы фиксированного размера, строки, битовые поля и
другие безымянные пользовательские типы или
union(ы
).
Типы поддерживают различные функциональности, связанные с
объектно-ориентированным программированием:
Разметка памяти
Типы располагают свои поля последовательно в памяти, используя нативное
выравнивание и правила заполнения (описано на странице
Field).
Особое внимание должно приниматься при использовании типов для файлового
ввода-вывода или взаимодействия с другими программами или языками
программирования, в случае, если выравнивание и правила отступов отличаются.
Необязательный спецификатор
Field = number
может использоваться для изменения поведения на стороне FreeBASIC.
Динамические данные
Типы могут содержать динамические строки, но обратите внимание, что тип
будет содержать дескриптор структуры
String,
а не строковые данные, которые динамически выделяются после создания типа и
могут быть переменной длины, таким образом, строковые данные не могут быть
вставлены в тип. Из-за этого сохранение такого типа в файл будет записывать
дескриптор строки, а не фактические данные строки. Для того, чтобы внедрить
строки в типы напрямую, необходимо использовать строки фиксированной длины.
Аналогично при сохранении динамических данных вручную с помощью указателей в
пределах типа, они обычно не имеет смысла для сохранения типа файла, потому
что будет записываться в файл адрес, хранящийся в поле указателя, а не
фактическую память, на которую он указывает. Адреса являются значимыми для
конкретного процесса , хотя и не могут совместно использоваться таким
образом.
Специальное примечание для строк фиксированной длины
В настоящее время поля строк фиксированной длины
String * N
имеют дополнительный нулевой завершающий символ на их конце, для
совместимости с C строками, что делает их несовместимыми с QB строками
внутри типов, потому что они на самом деле используют N + 1 байт, а не
просто N байт. Можно обойти это, объявив поле так:
As String * (N-1),
хотя это возможно не будет работать в будущих версиях, если нулевой
завершающий символ будет удален. Другой альтернативой является использование
массива
Byte или
UByte
с надлежащим размером.
Замечание
Вложенные безымянные типы или
Union(ы
)
не могут иметь функций-элементов.
Это пример типа QB-стиля, не включающий процедурные определения
Type clr
red As UByte
green As UByte
blue As UByte
End Type
Dim c As clr
c.red = 255
c.green = 128
c.blue = 64
А это пример типа, работающий в качестве объекта:
'' Пример, показывающий проблемы с фиксированной длиной
строковых полей в определяемых пользователем типах
'' Предположим, что мы прочитали заголовок GIF из файла
'' сигнатура ширина высота
Dim As ZString*(10+1) z => "GIF89a" + MKShort(10) + MKShort(11)
Print "Using fixed-length string"
Type hdr1 Field = 1
As String*(6-1) sig /' Мы
должны уменьшить строку на 1 символ
' чтобы
избежать смещений '/
As UShort wid, hei
End Type
Dim As hdr1 Ptr h1 = CPtr(hdr1 Ptr, @z)
Print h1->sig, h1->wid, h1->hei '' Печатаем GIF89 (пропускает
символ!) 10 11
'' Мы можем сделать сравнение только с 5 видимыми
символами и создания временной строки с LEFT
If Left(h1->sig, 5) = "GIF89" Then Print "ok" Else Print "error"
'' Использование массива UBYTE, нуждается
во вспомогательной функции для преобразования его в строку
Function ub2str( ub() As UByte ) As String
Dim As String res = Space(UBound(ub) - LBound(ub) + 1)
For i As Integer = LBound(ub) To UBound(ub)
res[i - LBound(ub)] = ub(i)
Next
Function = res
End Function
Print
Print "Using an array of ubytes"
Type hdr2 Field = 1
sig(0 To 6-1) As UByte '' 6
измерений
As UShort wid, hei
End Type
Dim As hdr2 Ptr h2 = CPtr(hdr2 Ptr, @z)
'' Просмотр и сравнение верно, но требуется
преобразование в строку
Print ub2str(h2->sig()), h2->wid, h2->hei '' Печатается GIF89a 10 11 (верно)
If ub2str(h2->sig()) = "GIF89a" Then Print "ok" Else Print "error" '' Печатает ok
См. также