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-8.5.0/cpp/Operator-Precedence-Problems.html