Уроки > Оператор присваивания. Запись значения в переменную на Си.
Мы не продаём знания — мы ими делимся!

Если для вас это ценно, то поддержите проект.

Ваша поддержка — топливо для новых уроков!

Оператор присваивания. Запись значения в переменную на Си

Пора разобраться, как использовать переменные по их прямому назначению — для хранения данных.

Основной вопрос такой: "Как сохранить значение в переменной?", или, вспоминая аналогию с коробкой, "Как положить что-то в коробку?"

Ответ прост. Для этого существует специальный оператор, который называется оператором присваивания и обозначается символом =. Обычно говорят не сохранить значение в переменную, а присвоить переменной значение.

Как работает оператор присваивания?

Сразу будем разбираться на примерах.

Листинг 1. Присваивание значения переменной

int z;	// объявляем переменную целого типа с именем z
z = 5;	// сохраняем в переменную число 5

double pi = 3.1415926; // создаём переменную и сразу присваиваем ей значение

В примере выше показаны два способа присвоить значение переменной. В первом случае мы сначала создаём переменную, а потом записываем в неё значение, а во втором — сразу создаём переменную и присваиваем ей значение. В умных книжках второй вариант записи ещё называют инициализация переменной. Так что, если где-то встретите выражение навроде проинициализируем вещественную переменную pi значением 3.1415926, то не пугайтесь.

Второй вариант записи (напоминаю, инициализация) короче, но делает всё то же самое, что и первый. Берёт значение, которое записано справа от знака равенства, и сохраняет его в переменную, которая записана слева от от него.

Частая ошибка!
Не забывайте ставить после очередной инструкции точку с запятой ;. Без неё компилятор не поймёт, где заканчивается одна инструкция (команда) и начинается другая.

Есть несколько важных моментов на которых надо заострить внимание:

  • в некоторых языках программирования, после того как вы создали переменную, в ней сразу же хранится значение нуль. В языке Си это не так. Пока переменной не присвоено какое-нибудь значение, в ней будет храниться "мусор". Как этот мусор выглядит, мы посмотрим на следующем уроке.

  • справа от знака равенства не обязательно должно быть записано какое-то конкретное число, там может быть записано, например, арифметическое выражение или имя другой переменной, объявленной ранее.

Остановимся на втором пункте подробнее. Чтобы лучше разобраться давайте обратимся к примерам.

Если справа от знака равенства записано выражение, то сначала вычисляется его значение и уже оно сохраняется в переменную, которая записана слева от =.

Листинг 2.

int n;
n = 1 + 2;	// В переменную n записываем значение 3

Важно!
Если переменной присваивается значение, то предыдущее значение, которое в ней было, удаляется.

Листинг 3.

int n = 10;	// Создаём переменную и записываем в неё 10
n = 5;	// Теперь в переменной записано значение 5, значение 10 удалено.

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

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

Листинг 4.

int n = 10, x = 0; 	// можно инициализировать сразу несколько переменных
n = 5; 	// теперь n равно 5
x = n - 3; // x будет равно 2 (5-3)

При вычислении выражения n - 3, n равняется 5. Это потому, что исходное значение 10, заданное при инициализации, мы в программе изменяли. А при вычислениях используется текущее значение переменной.

В выражении справа от знака равенства может быть использована сама переменная.

Листинг 5.

int n = 10;
n = n + 5; 	// n будет равно 15 (10 + 5)

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

Ещё один поучительный пример.

Листинг 6.

int x = 5, y = 0, z;
y = x + z; 	// что будет записано в переменной y?

Если вы подумали что 5, то вы ошиблись. Неизвестно, что в неё будет записано т.к. неизвестно, что было записано в переменную z. Ещё раз напоминаю: если переменной не присвоено никакое значение, в ней хранится не нуль, а неизвестно что.

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

Листинг 7.

int a = 2, b = 9, c = 4, D;

D = b*b - 4*a*c; 	// D будет равно 49 (9*9 - 4*2*4)

Почему именно так? У каждого арифметического действия есть свой "вес" , или, иначе говоря, приоритет. Например, вы уже наверняка знаете, что сначала в выражениях выполняется деление и умножение, а только потом вычитание и сложение. В программировании всё так же. Подробнее о приоритетах различных операций ещё будем говорить в следующих уроках.

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

Посмотрим несколько примеров.

Листинг 8.

int n, a = 2;
double x, pi = 3.14;
char s = 'k'; 	// сохраняем в переменную s символ k. 
                // Сам символ нужно написать в одинарных кавычках.

s = pi; // неправильно. В коробку для символов пытаемся положить вещественное число

n = a*pi; // неправильно. В коробку для целых чисел пытаемся положить 6.28 (2*3.14)

a = x; // неправильно. В целочисленную переменную пытаемся сохранить вещественное число

x = 2 + a;	// ДОПУСТИМО!!! x будет равно 4.0

Внимание на последнюю строчку! Хотя справа выражение целого типа, а слева вещественная переменная, данная команда всё равно будет работать так, как надо. Это из-за того, что все целые числа можно записать как вещественные, у которых дробная часть равна нулю. Подобное действие называется неявное приведение (преобразование) типов.

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

Практика

Исследовательские задачи для хакеров

  • В некоторые языках программирования, для вывода значения переменной на экран, её можно просто передать в качестве аргумента в ту же функцию, что и для вывода строки. Например,
# python
print("Hello, World!");

n = 10 

print(n)
// javascript
console.log("Hello, world!\n");

let n = 10;

console.log(n)
// php
echo "Hello, world";

$n = 10;

echo $n;

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

#include <stdio.h>

int main(void){
        int n = 10;

        printf(n); // Ошибка
}

Для того, чтобы вывести целочисленную переменную на консоль, нужно чуть-чуть изменить аргументы функции printf. Вот так:

printf("%d", n);

Что это означает и как это работает, мы разберём уже в следующем уроке, а пока можете самостоятельно поэкспериментировать с выводом целочисленных значений и переменных в консоль.

  • Кстати, теперь, зная, как выводить на экран значение переменной, попробуйте вывести на экран переменную типа int, которую вы объявили, но значение ей ещё не присвоили.

И напоминаю про хакерскую задачу из позапрошлого шага про типы данных. Теперь у вас есть всё, чтобы её выполнить.