Spec-Zone.ru › GCC 10 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 может быть изменено для решения этой проблемы, используя do … while выражение. Вот как это сделать:

#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-10.5.0/cpp/Swallowing-the-Semicolon.html

Spec-Zone.ru

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