MSVC неправильно расширяет __VA_ARGS__ - PullRequest
46 голосов
/ 27 февраля 2011

Рассмотрим этот код:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

Ожидаемый вывод X = 1 and VA_ARGS = 2, 3 для обоих макросов, и это то, что я получаю с GCC, однако MSVC расширяет это как:

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

То есть __VA_ARGS__ раскрывается как один аргумент, а не разбивается на несколько.

Есть ли способ обойти это?

Ответы [ 3 ]

45 голосов
/ 27 февраля 2011

Препроцессор MSVC, похоже, ведет себя совсем не так, как стандарт спецификация.
Вероятно, поможет следующий обходной путь:

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
21 голосов
/ 18 сентября 2011

Я отправил следующую проблему поддержки Microsoft :

Следующая программа выдает ошибку компиляции, потому что прекомпилятор неправильно __VA_ARGS__ расширяется:

#include <stdio.h>

#define A2(a1, a2) ((a1)+(a2))

#define A_VA(...) A2(__VA_ARGS__)

int main(int argc, char *argv[])
{
    printf("%d\n", A_VA(1, 2));
    return 0;
}

Препроцессор расширяет printf до: printf ("% d \ n", ((1, 2) + ()));

вместо printf ("% d \ n", ((1) + (2)));

Я получил следующий неудовлетворительный ответ от разработчика команды компиляторов Microsoft:

Привет: компилятор Visual C ++ в этом случае работает правильно. Если вы объединяете правило, что токены, которые соответствуют '...' при первоначальном вызове макроса, объединяются, чтобы сформировать единую сущность (16.3 / p12) с правилом, что вложенные макросы раскрываются перед заменой аргумента (16.3.1 / p1) ) тогда в этом случае компилятор считает, что A2 вызывается с одним аргументом: отсюда и сообщение об ошибке.

1 голос
/ 18 сентября 2011

Какую версию MSVC вы используете? Вам понадобится Visual C ++ 2010.

__VA_ARGS__ впервые был представлен C99. MSVC никогда не пытался поддерживать C99, поэтому поддержка не была добавлена.

Однако теперь __VA_ARGS__ включен в новый стандарт C ++, C ++ 2011 (ранее известный как C ++ 0x), который Microsoft, очевидно, планирует поддерживать, поэтому он был поддержан в последних версиях MSVC.

Кстати, вам понадобится суффикс .cpp к исходному файлу, чтобы получить эту поддержку. MSVC долгое время не обновлял свой веб-интерфейс C.

...