Spec-Zone.ru › GCC 10 CPP

Next: Проглатывание точки с запятой, Previous: Неправильное вложение, Up: Ошибки в макросах [Оглавление][Индекс]

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))

Next: Проглатывание точки с запятой, Previous: Неправильное вложение, Up: Ошибки в макросах [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/cpp/Operator-Precedence-Problems.html

Spec-Zone.ru

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