Spec-Zone.ru › GCC 12 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-12.1.0/cpp/Operator-Precedence-Problems.html

Spec-Zone.ru

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