Интересно о некоторых # уловках - PullRequest
1 голос
/ 25 апреля 2010

При чтении кодов моего группового проекта я сталкиваюсь со многими DEFINE, и некоторые из них кажутся странными. Чтобы обобщить это, пожалуйста, посмотрите на следующие 2 примера.

Пример 1:

#define SNPRINTF(dst, fmt, arg...)  snprintf(dst, sizeof(dst), fmt, ##arg)

что означает "##" в этих обстоятельствах? Я попытался удалить их обоих и написать коды, такие как "char buf [1024]; SNPRINTF (buf,"% s,% s "," abcd "," efg ");" который дал тот же результат. Так что "##" кажется бесполезным и не причиняет мне вреда.

Пример 2:

#define CLOSE(fd)   do  {   \
        if (-1 != (fd)) {   \
                    close(fd);  \
                    (fd)    = -1;   \
                }   \
} while (0)

Необходимо вставить внутренний код в оператор do{}while(0)? Какая польза?

Ответы [ 2 ]

8 голосов
/ 25 апреля 2010

... идентифицирует вариационный макрос в соответствии со стандартом C99. Токен, указывающий на расширение «всех оставшихся аргументов» в правой части, согласно стандарту, равен __VA_ARGS__ - я полагаю, что вы используете какой-то компилятор C с нестандартным расширением, которое допускает разные формы using (## является оператором вставки токена препроцессора, но я не понимаю, как это применимо здесь).

Вторая форма - классический трюк (даже старше, чем C89), обеспечивающий ; после правильного поведения макроса, else после того, как он не привязан к неправильному if, и так далее. По сути, упаковка нескольких условных операторов, необходимых для этого do ... while, безопасно «вкладывает» их в блок, который впоследствии требует точки с запятой, синтаксически «как если бы» вызов макроса был вместо вызова функции.

3 голосов
/ 25 апреля 2010

Два отвечают на ваши вопросы по порядку:

  1. является оператором вставки, и поэтому он ничего не делает там. Я думаю (не смог найти никаких ссылок), что есть нестандартные версии, которые будут есть предшествующую запятую, если она пуста, так что, возможно, это то, для чего это. Как уже упоминалось, вещь do{...}while(0) - это стандартная уловка, гарантирующая, что все, что вставлено в ..., может рассматриваться как одно утверждение. Как правило, он позволяет писать такие вещи, как:

if( floon )
  CLOSE(floon);

, не беспокоясь об этом.

...