C Урок 16. Операторы присваивания



Изучив в течение 15 предыдущих уроков очень многое из языка C, а также попрактиковавшись изрядно с данным языком в наших учебных проектах, мы поняли, что для того, чтобы переменная получила новое значение, его надо ей как-то присвоить. Для этого мы использовали оператор присваивания =.

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

Начнём с обычной базовой операции присваивания, которая обозначается вот так

 

=

 

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

Приведём несколько примеров присваивания

 

x = 15;

y = x + 1;

z = x * (y-5);

 

Мы можем применить несколько операций присваивания одновременно

 

z = y = x = 5;

 

Порядок выполнения нескольких операций присваивания в данном случае — справа налево. То есть, сначала результат выражения присваивается переменной x, затем значение переменной x присваивается переменной y а уж затем значение переменной y — переменной z.

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

 

y = x < 10;

 

Так как результат условий бывает лишь двух видов — ИСТИНА или ЛОЖЬ, что в математическом выражении — 1 или 0, то соответствующий результат и присвоится переменной, стоящей справа. Если x будет меньше 10, то присвоится 1, если нет — то 0.

Также присваивание может происходить в самом выражении, например выражении условия

 

while((y = x)>3)

{

   инструкции...

}

 

или

 

while((y = x))

{

   инструкции...

}

 

В данном случае в первом примере в условии цикла сначала выполнится выражение в скобках, то есть значение переменной x присвоится переменной y, затем уже значение переменной y проверится на то, что оно больше 3, И если это действительно так, то цикл продолжится, если нет — то выходим из цикла.

Во втором примере всё происходит аналогично, только проверяется равенство единице, так как ИСТИНА — это 1. Две пары скобок обязательны, так как внутренние скобки — это выражение, а внешние — условие цикла. Если будут скобки только одни — получим ошибку.

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

Если мы обозначим оператор, комбинируемый с базовым оператором присваивания OP, а операнды справа и слева обозначим o1 b o2, то операция с применением комбинированного оператора присваивания запишется вот так

 

o1 OP= o2;

 

А работает комбинированный оператор так: сначала между значением переменной o1 и значением выражения o2 выполняется операция OP, а затем результат этой операции присваивается переменной o1.

То есть команда, записанная нами, будет полностью эквивалентна следующей команде:

 

o1 = o1 OP o2;

 

 

Вот примеры таких операторов:

+= — присваивание со сложением,

-= — присваивание с вычитанием,

*= — присваивание с умножением,

/= — присваивание с делением,

%= — присваивание с делением по модулю,

&= — присваивание с операцией И (AND),

|= — присваивание с операцией ИЛИ (OR),

^= — присваивание с операцией ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR),

>>= — присваивание с битовым сдвигом вправо,

<<= — присваивание с битовым сдвигом влево.

 

А вот примеры операций с применением таких операторов

 

x += 5;

y -= x;

z *= x+5;

a /= 3;

b %= 10;

c &= 0x0F;

x |= 0x3A;

y ^= 0x55;

z >>= 2;

a <<= 5;

 

Стоит обратить внимание вот на эту инструкцию

 

z *= x+5;

 

Кто-то вполне может подумать, что она эквивалентна вот такой инструкции

 

z = z*x+5;

 

Но, зная правило работы комбинированных операторов присваивания, которое гласит о том, что сначала вычисляется выражение справа от оператора, а уж потом выполняется операция, стоящая перед знаком =, то эквивалентная операция будет вот такая

 

z = z*(x+5);

 

Теперь мы немало знаем об операторах присваивания и можем смело приступить к практической части урока.

Проект сделаем из проекта MYPROG15 прошлого занятия и имя ему было присвоено MYPROG16.

Откроем файл main.c и в функции main(), как обычно, удалим весь код тела кроме возврата нуля, останется от него вот это

 

int main()

{

  return 0; //Return an integer from a function

}

Удалим также вот эти константы

 

#define BIT0 0

#define BIT1 1

#define BIT2 2

#define BIT3 3

#define BIT4 4

#define BIT5 5

#define BIT6 6

#define BIT7 7

 

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

Добавим в функцию main() следующий код, в котором применим для начала самое простейшее присваивание переменной значения

 

 

Проверим, как это работает

 

 

Всё работает и всё присвоилось.

 

 

Идём дальше. Закомментировав данный код, добавим другой

 

 

Посмотрим результат

 

Также всё работает.

Теперь попробуем поиграть с условными выражениями

 

 

А вот и результат наших присваиваний

 

 

В первом случае — ИСТИНА, во втором — ЛОЖЬ.

Теперь комбинированные операторы присваивания.

Начнём с арифметических операторов

 

 

Проверим результаты наших операций в консоли

 

 

Теперь побитовые операции. В принципе, нет необходимости в примерах со всеми побитовыми операциями. Выполним парочку

 

 

Проверим результат

 

Операторы сработали как надо.

Теперь испытаем несколько присваиваний в одной команде

 

 

Проверим результат

 

 

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

 

 

А чтобы было с чем сравнить, то мы нашу команду с множественным присваиванием заменим на три команды с обычным присваиванием

 

 

В данном случае будет уже вот так

 

 

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

Теперь использование присваивания в условных выражениях.

Приведём пару примеров

 

 

В условии первого цикла значение переменной x присваивается переменной y, затем проверяется, что значение это больше трёх, при выполнении этого условия тело цикла выполняется. А в условии второго цикла также значение переменной x присваивается переменной y, а затем проверяется, что это значение истинно, или равно единице. Только тогда выполняется тело цикла. Поэтому, пока при декрементировании в теле цикла значения переменной x оно не достигнет единицы, цикл будет повторно выполняться.

Проверим это

 

 

Всё так и есть.

Итак, на данном уроке мы познакомились с различными операциями присваивания, поняли, что их бывает немало и проверили это на практике, тем самым лишний раз закрепили свои знания.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование на C Следующий урок

 

Исходный код

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

C Операции присваивания

Один комментарий на “C Урок 16. Операторы присваивания
  1. Иван:

    большое спасибо за урок.
    кажется, присваивание ерунда, а оказалось столько нюансов

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*