Базовый CS с нуля
Что такое значение
Ты уже знаешь, что память — это ряд пронумерованных ячеек, и в каждой ячейке хранятся биты. Ты знаешь, что CPU читает ячейку по адресу и получает обратно паттерн битов. Но вот вопрос, который те уроки оставили без ответа: что значат эти биты?
Предположим, ты читаешь ячейку памяти 7 и получаешь 8-битный паттерн 01000001. Что он
представляет? Это число 65? Буква «A»? Часть красного канала пикселя? Сами биты не
несут ярлыка. Они просто восемь переключателей — выключен и включён — ожидающих
интерпретации.
Этот урок даёт точное определение значению на уровне машины: фиксированный паттерн битов, лежащих в ячейках памяти. Ничего больше и ничего меньше — пока что-то не скажет, как их читать.
После этого урока ты сможешь определить значение как паттерн битов в ячейках памяти, объяснить, что биты сами по себе не несут смысла, проследить, как конкретное значение (число или символ) отображается в паттерн битов по определённому адресу, и объяснить, почему понятие интерпретации отделено от понятия хранения.
Значение — это биты в ячейках. Всё, с чем работает выполняющаяся программа, — числа, текст, цвета, решения истина/ложь — хранится в виде паттерна битов в ячейках памяти. Значение на уровне машины — это именно: непрерывный набор ячеек памяти, чьи биты, взятые вместе, кодируют некоторые данные.
Один байт (8 бит) по адресу 20 может содержать паттерн 01000001. Этот паттерн и есть
значение, хранящееся по адресу 20. Машине безразлично, что он означает; она просто хранит
восемь битов и может вернуть их по запросу.
Программа, которая туда записала эти биты, знает, что они значат. Больше никто — ни аппаратура памяти, ни арифметическое устройство CPU, ни шина. Биты пассивны. Они лежат в своих ячейках и ждут.
Биты не несут врождённого смысла. Этот момент тонкий, но фундаментальный. Паттерн
01000001 сам по себе ничего автоматически не означает. Это последовательность восьми
состояний «выключен/включён». Будет ли он означать:
- беззнаковое целое 65 (двоичные разряды: 64 + 1),
- символ ASCII «A» (код ASCII 65 соответствует «A»),
- что-то ещё,
— полностью зависит от того, как программа выбирает его читать. Паттерн битов одинаков; смысл — в способе чтения.
Сравни с физическим объектом: отвёртку можно использовать как рычаг или как зубило. Её форма не делает её тем или другим — решение человека применить её определённым образом делает. Биты — то же самое: их расположение фиксировано, но интерпретация — это выбор, сделанный в другом месте.
Значения живут по адресам. Поскольку значения — это паттерны битов в памяти, у каждого значения есть местоположение: адрес (или диапазон адресов), по которому лежат его биты. Однобайтовое значение занимает один адрес. Четырёхбайтовое — четыре последовательных адреса. Восьмибайтовое — восемь.
Чтобы использовать значение, программа должна:
- Знать, где оно лежит (начальный адрес).
- Знать, какого оно размера (сколько ячеек занимает).
- Знать, как интерпретировать биты в этих ячейках.
Все три знания раздельны. Аппаратура памяти обеспечивает только шаг 1 (получение ячеек по адресу). Шаги 2 и 3 — ответственность программы, и именно это предоставляет тип. (Типы — следующий урок.)
Запись и чтение значения. Когда программа сохраняет значение, она выбирает начальный адрес и записывает нужное число байт туда. Когда она извлекает значение, то читает те же байты с того же адреса. Возвращённые биты — это значение: сырые, без интерпретации, пока программа не применит смысл.
В таком языке, как TypeScript, ты никогда не управляешь адресами напрямую — среда выполнения делает это за тебя. Но базовая машинная операция всегда одна: записать биты в ячейки, прочитать биты из ячеек. Любая высокоуровневая операция со значениями построена на этом фундаменте.
Почему это работает
Зачем проводить такую чёткую границу между «битами в ячейках» и «смыслом»? Потому что это разделение объясняет почти каждую тонкую ошибку в программировании. Ошибки типов, переполнения буфера, неверная сериализация, порча данных — все они восходят к одному корню: какой-то код читал или записывал биты с не той интерпретацией, чем предполагалось. Понимание того, что биты не несут встроенного смысла, делает эти ошибки понятными, а не загадочными.
Прослеживаем значение от источника до ячеек.
Предположим, программа содержит присваивание const x = 65. Вот что происходит на
уровне машины в упрощённой модели:
-
Число 65 кодируется. В 8-битном беззнаковом двоичном представлении 65 — это
01000001(64 + 1). Это кодирование вычисляется во время компиляции или загрузки. -
Среда выполнения выбирает адрес. Допустим, она выбирает адрес 20 как место хранения для
x. Этот выбор делает распределитель памяти среды выполнения — программист его не видит. -
Биты записываются в память. CPU выполняет инструкцию сохранения: «записать байт
01000001по адресу 20». После завершения инструкции ячейка 20 содержит01000001. -
Позже программа читает значение. Когда используется
x, среда выполнения выдаёт инструкцию загрузки: «прочитать байт по адресу 20». Память возвращает01000001. Среда выполнения затем интерпретирует эти биты как целое число (потому что знает, чтоxхранит число) и получает число 65.
Одни и те же 8 битов прошли путь: идея → кодирование → хранение → извлечение → интерпретация. Каждый шаг отдельный. Биты в ячейке 20 — это одни и те же восемь состояний «выключен/включён» на протяжении всего пути: «значение 65» существует только на шагах 1 и 4, где программа применяет интерпретацию.
Частая ошибка
Распространённое заблуждение: «значение и есть число 65». На уровне машины значение —
это паттерн битов 01000001. «65» — человеческая интерпретация этого паттерна. Для
большинства высокоуровневого программирования это различие не важно — язык обрабатывает
его прозрачно. Но когда ты пересекаешь границы (записываешь значение в одном языке,
читаешь в другом; передаёшь байты по сети; читаешь двоичный файл) — различие становится
критическим. Две программы должны договориться об интерпретации, иначе одни и те же биты
дадут разные числа.
Ячейка памяти хранит 8-битный паттерн 01000001. Сколько битов занимает это значение?
Беззнаковый 8-битный двоичный паттерн 01000001 равен какому десятичному числу? (Подсказка: разряды справа: 1, 2, 4, 8, 16, 32, 64, 128.)
Четырёхбайтовое значение хранится начиная с адреса 100. Какой последний адрес оно занимает?
Ячейка памяти 50 хранит биты 00000000. Каким беззнаковым целым числом всегда декодируется паттерн 00000000?
Программа записывает число 255 в один байт по адресу 30. В 8-битном беззнаковом двоичном коде 255 — это 11111111. Сколько битов равны 1 в этом паттерне?
Что такое значение на уровне машины?
Значение на уровне машины — это паттерн битов, занимающий одну или несколько последовательных ячеек памяти. Биты хранятся по конкретному начальному адресу и занимают определённое число байт. Они пассивны: аппаратура памяти хранит и возвращает их, не заботясь о том, что они представляют. Смысл не в битах — он в интерпретации, которую применяет читающая их программа. Две программы, читающие один и тот же байт с разными интерпретациями, увидят разные значения. Это разделение между хранением и интерпретацией — ключевая идея, которую формализует понятие типа — и именно типы рассматривает следующий урок.