Хранение данных в программе: типы данных

Когда ты начинаешь изучать новый язык программирования, одной из первых вещей, которую ты должны вызубрить, являются типы данных языка. Практически каждая программа управляет данными, и для правильного управления этими данными ты должен полностью понимать доступные типы. Ошибки неправильного использования типа данных занимают второе место по сравнению с синтаксическими ошибками, но они намного сложнее. Компилятор может отлавливать синтаксические ошибки и некоторые ошибки неправильного приведения типа данных, но большинство ошибок возникают уже во время работы программы и часто только при использовании определённых типов данных. Такие прерывистые ошибки трудно найти и их трудно исправить. Знание вида, размера и ограничений данных поможет свести такие ошибки к минимуму.

Иерархия типов данных

У FreeBASIC есть все стандартные числовые типы данных, которые ты ожидаешь для базового компилятора, а также указатели, которые обычно ты найдёшь только в языках низкого уровня, таких как Си.

Типы данных
│
├───простые
│   │
│   ├───целочисленные
│   │   │
│   │   ├───знаковые
│   │   │
│   │   └───беззнаковые
│   │
│   ├───дробные (вещественные)
│   │
│   ├───логический
│   │
│   ├───указатели
│   │
│   └───ссылки
│
└───сложные
    │
    ├───перечисления
    │
    ├───массивы
    │
    ├───строки
    │
    ├───структуры
    │
    └───объединения

В данном уроке мы будем изучать простые типы данных.

Целочисленные типы данных

Основные типы данных: Byte, Short, Long, LongInt, Integer. К ним может добавляться приставка U, превращающая их в беззнаковый тип: UByte, UShort, ULong, ULongInt, UInteger.

Знаковые целые

Знаковые целые могут хранить в себе отрицательные значения, положительные значения и 0.

Знаковое целоеРазмер в памяти, байтРазмер в памяти, битМинимальное значениеМаксимальное значение
Byte18-128127
Short216-3276832767
Long432-21474836482147483647
LongInt864-92233720368547758089223372036854775807
Integer4 или 832 или 64Как у Long или LongIntКак у Long или LongInt

Диапазон хранимых значений для типа Integer зависит от битности платформы: на 32‐битной платформе такой же как у Long, на 64‐битной такой же как у LongInt.

Беззнаковые целые

Беззнаковое целые могут хранить в себе положительные значения и 0.

Беззнаковое целоеРазмер в памяти, байтРазмер в памяти, битМинимальное значениеМаксимальное значение
UByte18-128127
UShort216-3276832767
ULong432-21474836482147483647
ULongInt864-92233720368547758089223372036854775807
UInteger4 или 832 или 64Как у ULong или ULongIntКак у ULong или ULongInt

Диапазон хранимых значений для типа UInteger зависит от битности платформы: на 32‐битной платформе такой же как у ULong, на 64‐битной такой же как у ULongInt.

Дробные типы

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

Дробный тип данныхРазмер в памяти, байтРазмер в памяти, битМинимальное значениеМаксимальное значение
Single4321.1E-383.43E+38
Double864-2.2E-308+1.7E+308

Логический тип

Этот тип данных может принимать только два значения: истину True или ложь False. Технически представляет из себя целое число, все биты которого либо сброшены в 0, либо установлены в 1.

Логический типРазмер в памяти, байтРазмер в памяти, битМинимальное значениеМаксимальное значение
Boolean18TrueFalse

Из‐за того, что Boolean можно трактовать как знаковое число, вытекает интересное наблюдение. Если считать, что False — это 00000000, тогда истина True определяется как отрицание лжи. Отрицание нуля — это обращение всех бит числа на противоположное значение, то есть в 11111111. Знаковое число со всеми установленными битами — это -1. Следовательно, False равна нулю, а True — минус единице.

Указатель

Технически представляет из себя беззнаковое целое число, но на практике с указателем работают не как с числом, а как с особым типом данных, в котором хранится адрес памяти. Размер указателя зависит от платформы: на 32‐битной платформе такой же как у ULong, на 64‐битной такой же как у ULongInt, однако существуют и экзотические платформы, где это не так.

УказательРазмер в памяти, байтРазмер в памяти, битМинимальное значениеМаксимальное значение
<тип> Ptr или <тип> PointerЗависит от платформыЗависит от платформы0Зависит от платформы

Какой тип данных выбрать

Эмпирическое правило таково: использовать самый большой тип данных, который необходим для хранения ожидаемого диапазона значений. Это может показаться очевидным, но многие программы терпят неудачу, потому что программист не полностью понял диапазон данных в своей программе. Когда ты создаёшь программу, ты должен отображать не только логику программы, но и данные, связанные с каждым блоком логики. Когда ты наберёшь данные загодя, ты с меньшей вероятностью столкнёшься с ошибками типа данных. Например, если ты работаешь с кодами ASCII, которые варьируются от 0 до 255, то UByte будет хорошим выбором, так как диапазон UByte совпадает с диапазоном кодов ASCII, и ты используешь только 1 байт памяти.

Однако есть ещё одно соображение: «естественный» размер данных компьютера. В 32‐битной системе размер естественных данных составляет 4 байта или Integer. Это означает, что компьютер оптимизирован для обработки Integer и делает это более эффективно, даже если ты «теряешь» 3 байта памяти, используя Integer для кода ASCII.

В большинстве случаев Integer является хорошим универсальным выбором для целочисленных данных. Диапазон довольно велик, он обрабатывает как отрицательные, так и положительные числа, и тебе выгодно использовать естественный тип данных компьютера. Для данных с плавающей запятой Double является хорошим выбором, поскольку, как и Integer, он имеет хороший диапазон значений и лучшую точность, чем Single. Это только предложения; какой тип данных ты в конечном итоге используешь, будет определяться потребностями твоей программы.