Какую разрядность имеет Int в Swift на разных целевых платформах и когда это важно учитывать?

Какую разрядность имеет Int в Swift на разных целевых платформах и когда это важно учитывать?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Int — знаковый целочисленный тип с разрядностью, равной разрядности нативного машинного слова: обычно 64 бита на 64-битной платформе и 32 бита на 32-битной. Это удобно для обычных вычислений, но для бинарных форматов, сетевых протоколов, файлов и межъязыкового API следует явно выбирать Int32 или Int64, если размер числа является частью контракта.

Исторический контекст

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

Одновременно Swift предоставляет фиксированные типы Int8, Int16, Int32, Int64 и соответствующие беззнаковые варианты. Они решают другую задачу — гарантируют одинаковый диапазон и двоичное представление независимо от платформы.

Постановка проблемы

Если сохранить значение Int в файл или передать его по протоколу, предполагающему строго определённое количество байт, формат может зависеть от целевой платформы. На 32-битной системе значение, помещавшееся в 64-битный Int, может не поместиться в Int вообще.

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

Подробное решение

Разрядность можно определить через размер типа:

let bits = MemoryLayout<Int>.size * 8 print(bits)

Int хранит знаковые значения и обычно имеет диапазон от Int.min до Int.max, зависящий от его разрядности. На 64-битной платформе это диапазон 64-битного знакового целого, а на 32-битной — 32-битного.

Для индексов массивов, счётчиков элементов и размеров в памяти Int обычно является подходящим выбором: API коллекций Swift использует его, и преобразования не требуются. Для внешнего контракта выбирают фиксированный тип: например, Int32 для поля протокола, которое по спецификации занимает 4 байта.

Важно отличать разрядность типа от фактического значения. Небольшое число, хранящееся в Int, не становится автоматически 32-битным только потому, что помещается в такой диапазон. Тип остаётся Int, а его диапазон определяется платформой.

Ситуация из практики

Сервис передаёт количество миллисекунд в поле, определённом как знаковое 64-битное число. Разработчик объявляет это поле как Int, что работает на используемом 64-битном устройстве, но оставляет формат зависимым от платформы.

Вариант с UInt не подходит, если протокол допускает отрицательное значение для специального состояния. Вариант с Int удобен внутри приложения, но небезопасен на границе формата. Выбор Int64 фиксирует контракт, явно показывает ожидаемый размер и позволяет отдельно преобразовать значение в Int только там, где это требуется API платформы.

Что кандидаты часто упускают

1. Меняется ли размер Int в зависимости от значения?

Нет. Размер определяется типом и целевой платформой, а не конкретным числом. Значение 1 в Int не превращается в узкий целочисленный тип автоматически.

2. Всегда ли Int занимает столько же байт, сколько указатель?

На поддерживаемых Swift-платформах размер Int соответствует размеру нативного машинного слова и обычно совпадает с размером указателя, но полагаться на это как на формат сериализации не следует. Для таких контрактов нужно использовать тип с явно заданной разрядностью и проверять требования конкретного ABI или протокола.

3. Какой тип выбрать для индекса коллекции: Int или Int64?

Обычно Int, потому что стандартные операции индексации и размеры коллекций используют нативный целочисленный тип. Int64 имеет смысл, если индекс или количество является частью внешнего формата либо может превышать диапазон Int на поддерживаемых 32-битных платформах; тогда преобразование к типу индекса нужно выполнять явно и проверять его безопасность.