3.10.2 Проблемы с приоритетом операторов
Вы, возможно, заметили, что во многих примерах определения макросов выше, каждое вхождение имени аргумента макроса было заключено в скобки. Кроме того, обычно вся конструкция определения макроса окружена ещё одной парой скобок. Вот почему лучше писать макросы именно таким образом.
Предположим, вы определяете макрос следующим образом:
#define ceil_div(x, y) (x + y - 1) / y
целью которого является деление с округлением вверх. (Одно из применений этой операции — вычисление того, сколько int объектов необходимо для хранения определённого количества char объектов.) Затем предположим, что он используется следующим образом:
a = ceil_div (b & c, sizeof (int));
→ a = (b & c + sizeof (int) - 1) / sizeof (int);
Это не делает того, что предполагалось. Правила приоритета операторов C делают его эквивалентным этому:
a = (b & (c + sizeof (int) - 1)) / sizeof (int);
А нам нужно вот это:
a = ((b & c) + sizeof (int) - 1)) / sizeof (int);
Определение макроса как
#define ceil_div(x, y) ((x) + (y) - 1) / (y)
обеспечивает желаемый результат.
Нежелательное группирование может возникать и другим способом. Рассмотрим sizeof
ceil_div(1, 2). Это выглядит как выражение C, которое должно вычислить размер типа ceil_div (1, 2), но на самом деле оно означает нечто совершенно другое. Вот что из него получается:
sizeof ((1) + (2) - 1) / (2)
Это взяло бы размер целого числа и разделило его на два. Правила приоритета поместили деление за пределами sizeof, в то время как оно должно было быть внутри.
Скобки вокруг всего определения макроса предотвращают подобные проблемы. Итак, вот рекомендуемый способ определения ceil_div:
#define ceil_div(x, y) (((x) + (y) - 1) / (y))
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/cpp/Operator-Precedence-Problems.html