C Урок 17. Приоритет операций



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

 

Уровень прио- ритета Опе-
ратор
Наименование оператора Порядок выполнения
1 ( ) Вызов функции слева направо
[ ] Обращение к массиву по индексу
-> Выбор элемента структуры или объединения по указателю
. Выбор элемента структуры или объединения по ссылке
2 ! Логическое отрицание справа налево
~ Побитовое отрицание
++ Инкрементирование
Декрементирование
+ Унарный плюс
Унарный минус
* Обращение по адресу, разыменовывание
& Взятие адреса
(type) Приведение типа
sizeof Размер
3 * Умножение слева направо
/ Деление
% Деление по модулю
4 + Сложение слева направо
Вычитание
5 >> Сдвиг битов вправо слева направо
<< Сдвиг битов влево
6 < Меньше слева направо
<= Меньше или равно
> Больше
>= Больше или равно
7 == Равенство слева направо
!= Неравенство
8 & Побитовое И (AND) слева направо
9 ^ Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) слева направо
10 | Побитовое ИЛИ (OR) слева направо
11 && Логическое И слева направо
12 || Логическое ИЛИ слева направо
13 ?: Тернарная операция справа налево
14 = Присваивание справа налево
+= Сложение с присваиванием
-= Вычитание с присваиванием
*= Умножение с присваиванием
/= Деление с присваиванием
%= Деление по модулю с присваиванием
&= Побитовое И с присваиванием
^= Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ с присваиванием
|= Побитовое ИЛИ с присваиванием
<<= Побитовый сдвиг влево с присваиванием
>>= Побитовый сдвиг вправо с присваиванием
15 , Операция запятая слева направо

 

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

Вот такой вот таблицы мы и будем придерживаться в проектировании наших выражений в коде.

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

 

 

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

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

 

int main()

{

  return 0; //Return an integer from a function

}

 

Первый пример кода будет самый простой. Добавим вот такой код в функцию main()

 

 

Здесь используются операторы с одинаковым приоритетом — сложение и вычитание. Данные операции выполняются обычным образом в порядке «слева направо».

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

 

 

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

 

 

Посмотрим на результат вычислений

 

 

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

 

 

Идём дальше. Добавим вот такую функцию, у нас она когда-то уже была

 

 

Добавим ещё одну функцию

 

 

Данная функция аналогичная, только вместо деления она считает сумму двух аргументов и возвращает её.

Закомментировав предыдущий код в функции main(), добавим вот такой с использованием наших функций

 

 

Здесь в первом случае мы к значению xf прибавляем возвращённое из функции my_div значение, которое является результатом деления значения yf на значение zf. Понятно, что сначала выполнится функция, а потом уже прибавится возвращённое из неё значение.

Во втором случае мы уже мы делим значение xf на возвращённую из функции my_sun сумму значений yf и zf. Думаю, никому в голову не придёт то, что у суммы меньше приоритет. Здесь это работает засчёт аргументов функции, которые объединены в такие скобки, которые имеют очень высокий приоритет.

Посмотрим результат работы нашего кода

 

 

Попробуем поиграть с приоритетами в условном операторе if

 

 

Если мы не знаем приоритеты, нам, конечно же захочется эти две суммы объединить каждую в свои скобки. Да, может, оно и к лучшему, мне кажется, что так было бы намного читабельнее, хотя, может, я привык к скобкам. А на самом деле скобки здесь никакие не нужны, так как у операторов сравнения приоритет меньше, чем у операторов арифметических.

Проверим работу нашего кода

 

 

Всё правильно!

Об этом говорит даже не сколько результат, а отсутствие ошибки при сборки. Если бы нужны были скобки, то сборка бы не состоялась из-за ошибки в коде.

Вывод: никакие скобки не нужны.

Теперь давайте поиграем с побитовыми операциями

 

 

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

Проверим это

 

 

Результат всё подтвердил. Операция ИЛИ выполнилась уже со сдвинутым вторым операндом.

Ещё немного потренируемся с логическими операторами, написав вот такой пример

 

 

Здесь сначала должна выполниться операция ИСКЛЮЧАЮЩЕЕ ИЛИ, а затем обычное ИЛИ. Так как у XOR приоритет выше.

Мало того, компилятор «подумает», что вдруг мы не знаем приоритетов операции и думаем что сначала выполнится ИЛИ и предложит нам применить скобки! Понимая то, что мы намеренно хотим выполнить сначала XOR, слушаться мы его не будем, а просто выполним наш код

 

 

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

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

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

 

 

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

 

Исходный код

 

 

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

 

C Приоритет операций

3 комментария на “C Урок 17. Приоритет операций
  1. Андрей:

    Из результата видно, что если бы сначала выполнилось обычное ИЛИ, то он был бы совершенно другим
    По правде говоря, в данном случае не совсем так.

  2. Попробовал решить последний пример двумя способами: сначала XOR, а затем OR, и наоборот, сначала OR, а затем XOR.
    Цитата была следующей: «Из результата видно, что если бы сначала выполнилось обычное ИЛИ, то он был бы совершенно другим.»
    Однако, к моему удивлению, результат таки оказался одинаковым… Так что пример не совсем удачный, как мне кажется… Могу даже скриншот прислать (только вот куда?)

    Вот мои расчёты (надеюсь, при публикации настройки не съедут):
    //
    // res = a | b ^ c
    //
    // a = 0b00111000, b = 0b10000010, c = 0b01000001
    //
    //
    // res = a | (b ^ c) res = (a | b) ^ c
    //
    // b ^ c a | r1 a | b r2 ^ c
    // 0b10000010 0b00111000 0b00111000 0b10111010
    // ^ | | ^
    // 0b01000001 => 0b11000011 0b10000010 => 0b01000001
    // ========== ========== ========== ==========
    // 0b11000011 0b11111011 0b10111010 0b11111011
    // Result: 0b11111011 == Result: 0b11111011
    //

  3. Попробую с TAB'ами выложить вместо пробелов. Если что, можно будет скопировать и вставить в Notepad++: там будет всё нормально с форматированием.

    //
    // res = a | b ^ c
    // a = 0b00111000, b = 0b10000010, c = 0b01000001//
    //
    // res = a | (b ^ c) res = (a | b) ^ c
    // b ^ c a | r1 a | b r2 ^ c
    // 0b10000010 0b00111000 0b00111000 0b10111010
    // ^ | | ^
    // 0b01000001 => 0b11000011 0b10000010 => 0b01000001
    // ========== ========== ========== ==========
    // 0b11000011 0b11111011 0b10111010 0b11111011
    // Result: 0b11111011 == Result: 0b11111011
    //

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

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

*