Автор: mabu (Корпорация «Пакетные файлы»)

Опубликовано:

Исправлено:

Версия документа: 1.0

Секреты и хитрости

В этой статье собраны советы по написанию быстрого и компактного кода. Некоторые советы специфичны для фрибейсика, некоторые для всех языков программирования, некоторые для операционной системы Windows.

Деление чисел с плавающей запятой

Если у вас числа с плавающей запятой (Single или Double), то для повышения точности вычислений лучше не делить на N, а умножать на десятичную дробь из (1 / N).

Например, вместо деления на 2,0 следует умножать на 0,5; вместо деления на 3,0 — умножать 0,3(3), и так далее:

' У этой операции относительная погрешность будет больше
Dim Result As Double = 1.5 / 2.0

' Так будет точнее
Dim Result As Double = 1.5 * 0.5

Объявление переменных вместе с инициализирующим значением

В старом стиле бейсика приходилось сначала объявлять переменную, а потом присваивать ей значение:

Dim Width As Integer
Width = 640
Dim Height As Integer
Height = 480

В новом стиле переменные можно объявлять вместе с инициализирующим значением:

Dim Width As Integer = 640
Dim Height As Integer = 480

Используйте объявления переменных в новом стиле, это работает быстрее. В старом стиле получается, что сначала переменные будут инициализированы, а потом им присваивается значение.

Прекращение инициализации переменных по умолчанию

При объявлении новой переменной ей сразу же присваивается значение по умолчанию, если мы не сделали это сами:

Если нам не требуется инициализация переменных, для этого переменной нужно присвоить специальное значение Any:

' Этой переменной значение по умолчанию не будет присвоено
' Сейчас в ней находится так называемый «мусор»
Dim Count As Integer = Any

В случае со строками необходимо поставить нулевой символ самостоятельно:

' Память под строку выделена
Dim Value As WString * (MAX_BUFFER_LENGTH + 1) = Any

' Не забываем установить нулевой символ:
Value[0] = 0

Массивы без инициализации дескриптора массива

Массив во фрибейсике — это встроенный объект (дескриптор массива), в котором хранится размер каждого из измерений и указатель на данные. При объявлении массива фрибейсик автоматически создаёт дескриптор массива и инициализирует его поля. Это необходимо для контроля за границами и передачи массива в подпрограммы.

Однако если массив объявлен внутри структуры или с модификатором Shared, то фрибейсик будет контролировать границы массива на этапе компиляции без создания дескриптора массива.

Воспользуемся этой особенностью и создадим структуру, содержащую в себе массив фиксированной длины:

Const INTEGERVECTOR_CAPACITY = 512

Type IntegerVector
	Buffer(INTEGERVECTOR_CAPACITY - 1) As Integer
End Type

Теперь компилятор знает размер массива, и мы можем использовать экземпляр структуры с массивом внутри:

Dim Vector As IntegerVector = Any

For i As Integer = 0 To INTEGERVECTOR_CAPACITY - 1
	Vector.Buffer(i) = i
Next

Проверка строк на пустоту

Если нужно проверить не пуста ли строка, то следует использовать функцию Len:

If Len(s) Then
	' строка не пуста
End If

Сравнение строки с литеральной константой "" работает медленнее, потому что требует сравнения символьных данных:

If s = "" Then
	' строка пуста
	' этот код работает медленнее
End If

Использование строковых констант

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

Const MyConst = "Это константа"

Быстрая очистка (обнуление) строки

Для этого достаточно присвоить 0 первому символу в строке, то есть символу под индексом 0:

Dim Value As WString * (MAX_BUFFER_LENGTH + 1) = Any

Value[0] = 0

Получение символа в строке

Новички нередко используют функцию Mid для получения единственного символа в строке, однако есть способ проще.

Строка — это массив символов, следовательно, к ней можно применять индексирование по указателю:

' Строка длиной в 99 символов (+1 на нулевой)
Dim s As WString * (99 + 1) = Any

' Получение пятого символа в строке
Dim charCode As Integer = s[4]

Посимвольный обход строки

Предыдущий подход можно применять для посимвольного обхода строки в цикле. Проверяя текущий символ, цикл остановится как только встретится нулевой, обозначающий конец строки. Таким образом вычислять длину строки заранее не нужно:

Dim Value As WString * (MAX_BUFFER_LENGTH + 1) = Any

Dim i As Integer

Do While Value[i] <> 0
	' Что‐то сделать с символом
	' Например, вывести на консоль
	Print Value[i]
	
	' Сдвигаем индекс на следующий символ
	i += 1
Loop

Если заранее известно, что строки будут ненулевой длины, то условие выхода из цикла While s[i] <> 0 можно поставить после Loop.

Выравнивание структур

В объявлении структур старайся располагать поля по убыванию их размера. Особенно нужно уделить внимание группировке вместе переменных, чей размер меньше текущей архитектуры: Byte, Short, Long, Boolean, их массивы и структуры с ними.

Например, обращение к переменной с типом Integer по выровненному адресу занимает всего один такт процессора, а если переменная не выровнена, то два такта на архитектуре i386. На некоторых архитектурах читать по невыровненному адресу вообще нельзя. Так происходит потому, что невыровненная переменная располагается в нескольких ячейках памяти: часть в одной и часть в следующей.

Такой код работает медленно:

Type Foo
	Field1 As Boolean
	Field2 As Integer
End Type

Такой код работает быстро:

Type Bar
	Field2 As Integer
	Field1 As Boolean
End Type