Все файлы на компьютерах изначально выглядят как нули и единицы. Разные программы умеют интерпретировать их так, что мы получаем файлы: текст, музыку, видео. Но чтобы в памяти появились эти нули и единицы, их нужно туда положить.
Сегодня вспоминаем, как это выглядит на уровне железа компьютера и как можно записать в память данные, то есть присвоить ячейкам памяти какое-то значение.
Из чего состоит память компьютера
Оперативная память компьютера RAM состоит из огромного количества маленьких ячеек. Каждая такая ячейка хранит бит информации, который равен либо 0, либо 1.
В современных компьютерах чаще используется Dynamic RAM или DRAM. В ней каждая ячейка памяти состоит из элементов конденсатора и транзистора. Конденсатор хранит электрический заряд, а транзистор работает как переключатель.
Про транзисторы мы рассказывали. Это очень простой прибор, к которому подключены 3 контакта. На 1-й из них подаётся ток. Чтобы этот ток прошёл сквозь транзистор и вышел через 3-й контакт, нужно подать ток на средний 2-й. Этот 2-й контакт ещё называют «управляющая нога»:
Работает всё просто: если заряд есть, бит считается за 1, а если нет — за 0. То есть данные — это буквально микроскопические электрические состояния внутри чипа памяти.
Посмотрите, это схема матрицы DRAM-памяти. Именно так устроена обычная оперативная память в компьютере:
Возле конденсаторов на схеме стоит 1 или 0.
Word line — это строки памяти. Когда процессор хочет обратиться к строке памяти, он активирует одну word line, и транзисторы этой строки открываются. То есть вся строка становится доступной для чтения или записи.
Bit line — колонки памяти. По ним передаются электрические сигналы: чтение бита и запись бита. Каждая колонка соединяет все ячейки в столбце.
Если мы хотим записать в память какое-то число, физически в машине заряжаются и разряжаются конденсаторы. При этом конденсаторы плохо держат заряд, поэтому железо компьютера перезаписывает эти значения много раз за секунды. Физически память считывает все биты из одной строки и перезаписывает те, которые хранят 1 бит. Всё это происходит очень быстро, по частям и распределено специальным умным образом, поэтому процессор этого почти не замечает. А значит, и конечным пользователям компьютера это незаметно.
Когда программы читают эти значения, то понимают их по-разному. Иногда это можно указать вручную, например изменяя расширение файла: .jpg или .png. На содержание битов расширение не повлияет, но для софта на компьютере это будут разные инструкции.
Что такое присваивание в программировании
Присваивание в программировании — это базовая операция, которая связывает переменную с каким-то значением.
Получается, что программа берёт данные и записывает их в переменную, чтобы потом использовать в вычислениях. Без этого невозможно работать с переменными, потому что именно присваивание позволяет сохранять и изменять данные.
У каждой переменной есть область памяти, где хранится значение. Это адреса ячеек с транзисторами и конденсаторами. Когда программа выполняет присваивание, она записывает новые данные в эту область памяти.
В реальной разработке присваивание используется постоянно. Например, интернет-магазин получает цену товара из базы данных и сохраняет её в переменной. Потом эта переменная участвует в другой бизнес-логике приложения: расчёте скидок, налогов и итоговой стоимости заказа.
Как это может выглядеть на примере присваивания в языке Python:
# создаём переменную age и записываем в неё число 25
age = 25
# создаём переменную name и записываем строку
name = "Alex"
# выводим значения переменных
print(age)
print(name)
Команды вывода на экран покажут нам, что хранится в ячейках:
25
Alex
Как работает алгоритм присвоения значений
Когда программа выполняет присваивание, в операции всегда участвуют левостороннее выражение и правостороннее. Эти части определяют, куда будет записано значение и откуда оно берётся.
Слева стоит переменная или ссылка на ячейку памяти, туда программа будет записывать результат. Справа — само значение или формула, которую нужно вычислить. Сначала программа вычисляет выражение справа, а затем записывает готовый результат в переменную слева. То есть сначала выполняются вычисления, а потом — запись.
Например:
# создаём переменную price
price = 100
# вычисляем новое значение и записываем его в ту же переменную
price = price + 20
# выводим результат
print(price)
Что происходит внутри программы:
- Сначала берётся значение переменной price.
- К нему прибавляется 20.
- Получается новое число — 120.
- Это значение записывается обратно в переменную
price.
Как выглядит знак присваивания в программировании
Специальный знак присваивания в программировании есть во всех языках. Этот символ-оператор показывает программе, что значение справа нужно записать в переменную слева.
В большинстве популярных языков используется обычный знак равенства =. Он применяется в Python, JavaScript, Java, C++. Обратите внимание, что этот символ означает не математическое равенство, а запись значения в переменную.
Иногда в других языках используется другой синтаксис. Например, := в Pascal и Go, <- в R и некоторых функциональных языках. Так разработчики отделяют присваивание от математического равенства.
Виды операторов присваивания
В разработке есть несколько разновидностей таких операторов. Они позволяют по-разному записывать значения в переменные и часто делают код короче и понятнее.
Обычно операции присваивания делят на два типа: простые и составные, расширенные. Ещё современные языки поддерживают множественное присваивание, когда значения записываются сразу в несколько переменных.
Каждый из этих вариантов используется в разных ситуациях.
Простое присваивание
Это самый основной, базовый вариант. Программа просто берёт значение справа и записывает в переменную слева.
Пример на Python:
# создаём переменную x
x = 5
Здесь происходит всего одно действие. Число 5 записывается в переменную x. Если позже выполнить ещё одно присваивание, старое значение будет заменено новым. То есть можно написать так:
# создаём переменную x
x = 5
# изменяем значение переменной
x = 10
Тогда в x будет храниться только одно значение, которое записали последним — 10.
Почти во всех реальных проектах простое присваивание используется постоянно. Например, программа получает данные пользователя из формы и сохраняет их в переменные перед обработкой.
Составное (расширенное) присваивание
Это вид конструкций, который называется «синтаксическим сахаром». Они удобные, короткие и ускоряют чтение кода.
Составное присваивание объединяет арифметические операторы, такие как сложение или умножение с присваиванием. Вот примеры таких составных операторов:
+=-=*=/=%=
А вот пример использования:
# создаём переменную a
a = 10
# увеличиваем значение на 2
a += 2
То же самое будет, если написать так:
a = a + 2
Но a += 2 короче и легче читается.
В реальной разработке такие операторы часто используются в циклах. Например, когда программа подсчитывает количество пользователей на сайте или суммирует значения в списке:
# создаём переменную для накопления суммы
total = 0
# запускаем цикл от 1 до 5
for i in range(1, 6):
# прибавляем текущее значение i к total
total += i
# выводим результат
print(total)
При запуске программа возьмёт числа от 1 до 5 и будет прибавлять их к значению переменной total, которая в начале равна 0. То есть все числа от одного до 5 суммируются в одной переменной. Поэтому при запуске получаем сумму:
15
Параллельное (множественное) присваивание
Современные языки программирования позволяют присваивать значения сразу нескольким переменным. Это и называется параллельным или множественным присваиванием. Например, в Python можно записать код так:
# присваиваем значения двум переменным
a, b = 1, 11
print(a)
print(b)
Что получается при выполнении:
1
11
Python распределяет значения по порядку. Сначала значение получает первая переменная, потом вторая.
Ещё одна полезная возможность — быстро менять значения переменных местами:
x = 5
y = 10
# меняем значения местами
x, y = y, x
print("x = ", x)
print("y = ", y)
Проверяем результат:
x = 10
y = 5
Без этой функции пришлось бы создавать дополнительную временную переменную.
Полезный блок со скидкой
Если вам интересно писать код и вы хотите разобраться, какой язык программирования выбрать для старта, — держите скидку 16% на все курсы Практикума. Она действует до 31 марта.
Отличие присваивания от равенства
Присваивание с проверкой равенства иногда путают, потому что они выглядят похоже. В программировании это две разные операции. Тут надо запомнить правило записи.
Присваивание — это именно одинарный символ =. Он используется для записи значения в переменную. После выполнения операции состояние программы изменяется, потому что переменная получает новое значение.
Сравнение или равенство обычно записывается как == (или === в JavaScript). Оно не изменяет данные, а только проверяет условие равенства двух частей и возвращает логический результат: True или False.
Пример на Python:
# создаём переменную
x = 5
# проверяем условие
print(x == 5)
Запускаем и получаем:
True
При этом в переменную ничего не записалось.
В реальных программах оператор сравнения часто используется в условиях:
# сохраняем роль пользователя
role = "admin"
# проверяем, является ли пользователь администратором
if role == "admin":
print("доступ к настройкам разрешён")
Если перепутать = и ==, программа может начать работать неправильно. Например, условие будет выполняться всегда или вообще вызовет ошибку.
А ещё сравнение тоже может быть составным, например:
# проверяем возраст пользователя
age = 18
if age >= 18:
print("доступ разрешён")
Частые ошибки новичков
Вот несколько вещей, которые могут стать причиной багов и ошибок.
Использование переменной до её создания. Это одна из самых распространённых проблем. Если программа пытается прочитать значение переменной, которая ещё не была объявлена, возникает ошибка. Пример:
# пытаемся вывести переменную
print(score)
# создаём переменную позже
score = 10
В этом случае программа выдаст ошибку, потому что переменная ещё не существует:
NameError: name 'score' is not defined
Установка неправильного типа данных. В строго типизированных языках нельзя записывать строку в переменную, которая предназначена для чисел. Например, в Java или C++.
Это правило касается типов данных, а также скорости и надёжности программы. Если для каждой переменной чётко указать, какое значение она может принимать, приложения и сервисы можно делать быстрее, и работать они будут предсказуемее. Но работать с такими программами сложнее, потому что нужно следить за многими вещами сразу.
Пример такой строгой типизации на Java:
int age = 25;
age = "twenty five";
Компилятор выдаст ошибку, потому что строка не может быть записана в переменную типа int:
error: incompatible types: String cannot be converted to int
Случайная перезапись значения. Например, разработчик может повторно присвоить переменной новое значение и потерять предыдущие данные.
В реальной разработке такие ошибки могут приводить к серьёзным багам. Например, если случайно перезаписать переменную с ценой товара, программа может показать пользователю неправильную стоимость заказа. Поэтому иногда данные нужно делать неизменяемыми — для этого создают специальные переменные-константы.
Бонус для читателей
Если вам интересно писать код и вы хотите разобраться, какой язык программирования выбрать для старта, — держите скидку 16% на все курсы Практикума. Она действует до 31 марта.
