Spec-Zone.ru › GCC 7 CPP

3.10.3 Проглатывание точки с запятой

Зачастую желательно определить макрос, который раскрывается в составное операторное выражение. Рассмотрим, например, следующий макрос, который перемещает указатель (аргумент p указывает, где его найти) через символы пробела:

#define SKIP_SPACES(p, limit)  \
{ char *lim = (limit);         \
  while (p < lim) {            \
    if (*p++ != ' ') {         \
      p--; break; }}}

Здесь обратный слэш-новая строка используется для разделения определения макроса, которое должно быть единственной логической строкой, таким образом, чтобы оно напоминало способ расположения такого кода, если бы он не был частью определения макроса.

Вызов этого макроса может быть SKIP_SPACES (p, lim). Строго говоря, вызов раскрывается в составное операторное выражение, которое является полным операторным выражением без необходимости точки с запятой для его завершения. Однако, поскольку он выглядит как вызов функции, для минимизации путаницы можно использовать его как вызов функции, добавив после него точку с запятой, как в SKIP_SPACES (p, lim);

Это может вызвать проблемы перед else операторными выражениями, так как точка с запятой на самом деле является операторным выражением-пустотой. Предположим, вы пишете

if (*p != 0)
  SKIP_SPACES (p, lim);
else …

Наличие двух операторных выражений — составного операторного выражения и операторного выражения-пустоты — между if условием и else делает код на C некорректным.

Определение макроса SKIP_SPACES можно изменить, чтобы решить эту проблему, используя операторное выражение-пустоту. Вот как:

#define SKIP_SPACES(p, limit)     \
do { char *lim = (limit);         \
     while (p < lim) {            \
       if (*p++ != ' ') {         \
         p--; break; }}}          \
while (0)

Теперь SKIP_SPACES (p, lim); раскрывается в

do {…} while (0);

что является одним операторным выражением. Цикл выполняется ровно один раз; большинство компиляторов не генерируют дополнительный код для него.

Далее: Дублирование побочных эффектов, Предыдущий: Проблемы с приоритетом операторов, Вверх: Ловушки макросов [Содержание][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Swallowing-the-Semicolon.html

Spec-Zone.ru

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