Spec-Zone.ru › GCC 14 CPP

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API