Вы пишете то, что имеете в виду. Компилятор читает то, что хочет.
Если вы когда-либо смотрели на строку кода на C, будучи уверенным, что она делает одно, а затем наблюдали, как она делает совершенно другое, вы встретились с приоритетом операторов. Это не ошибка. Это особенность языка, которая кусает даже опытных разработчиков.
Возьмем эту простую арифметику:
x=5+3*6;
В школе математики говорят: сначала сложение. В C говорят: нет. Умножение и деление находятся на более высоком уровне, чем сложение и вычитание. Компилятор сначала умножает 3 на 6. Затем прибавляет 5. X получает 23. Не 48. Вы только что потеряли баллы на тесте. Или, что хуже, на продакшен-развертывании.
Заблуждение углубляется, когда вы смешиваете операторы с синтаксисом.
Посмотрите на это объявление:
char *a[10];
Является ли a указателем на массив из 10 символов? Или это массив из 10 указателей на символы?
Не зная конкретных правил приоритета, вы гадаете. В C квадратные скобки [] связывают строже, чем указатели *. Таким образом, это массив из 10 указателей на символы.
Это имеет значение, потому что C не разбирается как английский. Он разбирается как жесткая иерархия.
Вы можете написать код, который выглядит правильно, но терпит неудачу молча из-за приоритета.
Рассмотрим арифметику указателей, смешанную с доступом к структурам.
*p.i = 10;
Это не работает так, как ожидается. Оператор точка . имеет более высокий приоритет, чем оператор разыменования *. Компилятор пытается получить доступ к члену i объекта, на который указывает p, до разыменования p. Но p — это указатель, а не структура. Компилятор спотыкается. Или, что хуже, он интерпретирует память таким образом, что приводит к повреждению данных.
Вам нужно настоять на своем.
(*p).i = 10;
Скобки побеждают. Всегда.
Иерархия операторов
Керниган и Ритчи, архитекторы C, изложили приоритет в своем классическом тексте. В таблице ниже показан порядок. Верхняя строка — наивысший приоритет. Нижняя — наименьший.
- Скобки
()и Индексация[]- Слева направо.
- Унарные операторы
++,--,+,-,!,~,(type),*(разыменование),&(адрес),sizeof- Справа налево.
- Мультипликативные
*,/,%- Слева направо.
- Аддитивные
+,-- Слева направо.
- Сдвиг
<<,>>- Слева направо.
- Отношения
<,<=,>,>=- Слева направо.
- Равенство
==,!=- Слева направо.
- Побитовое И
&- Слева направо.
- Побитовое исключающее ИЛИ
^


























