Раздел 41 · Zig с нуля

Массивы и многоуказатели

junior~10 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Массивы и многоуказатели

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

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

Одна мысль урока

Массив хранит элементы и фиксированную длину, многоуказатель хранит адрес без длины.

Опора из прошлого урока: Опциональные типы вместо null.

От картинки к записи

Массив [3]u16 содержит ровно три числа. Длина известна при компиляции. Запись [_]u16{ 4, 5, 6 } просит вычислить длину из перечисления, поэтому её тип тоже [3]u16. Символ _ здесь не означает бесконечный список.

Присваивание массива другому имени копирует значение. Если затем изменить элемент копии, исходник сохранится. Это отличается от среза, который копирует только адрес и длину. Слова «копировать список» недостаточно: нужно назвать, копируются ли сами элементы или только представление доступа к ним.

Указатель *[3]u16 содержит адрес массива, длина остаётся в типе. Он не содержит ещё одну копию трёх чисел. Многоуказатель [*]u16 знает тип элемента и адрес начала, но не количество элементов. Индексация возможна, а автоматическая проверка длины отсутствует: сравнивать индекс не с чем.

Почему такой тип вообще существует? Некоторые внешние функции, особенно на границе с C, принимают адрес и длину отдельными параметрами. Чтобы вызвать их, нужно передать slice.ptr и slice.len. Внутри собственного кода чаще удобнее хранить обе части вместе как срез. Это не вопрос красоты, а сохранение сведений о границе.

Из многоуказателя можно создать срез pointer[0..count], но правильность count обязан знать автор. Запись не спрашивает у памяти, сколько там объектов. Если договор говорит, что за адресом лежат три числа, срез длины три уместен. Если длина пришла из недоверенного источника, одна эта запись не проверит правду.

Встречается и указатель с завершителем [*:0]const u8. Его договор говорит, что последовательность заканчивается нулём. Это не хранит длину: для её получения нужно найти завершитель. Ноль внутри обычного массива не сокращает массив автоматически, а конец среза по-прежнему задаёт len. Такие разновидности рассмотрим в связи со строками и C.

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

премиум-урок

Продолжение в премиуме: 1 200 ₽ в месяц или 10 000 ₽ в год. Вместе с ним серверные проверки задач и школьные токены AI-коуча.

Оплата пока не подключена: премиум и курсы открываются промокодом.