Макросы препроцессора как параметры для других макросов

Следующий код С++ компилируется и работает как программист, предназначенный для GCC (4.0.4)

#define FOO(x,y,z) ((x)*(y)*(z))
#define BAR(x) FOO(x,1)
#define BAZ 3,7

int main()
{
    return BAR(BAZ); /* interpreted as return ((3)*(7)*(1)); */
}

Однако макросы вызывают ошибку в Microsoft Visual С++ Express 2010:

main.cpp(7): предупреждение C4003: недостаточно фактических параметров для макроса "FOO"
    main.cpp(7): ошибка C2059: синтаксическая ошибка: ')'

Проблема заключается в том, что компилятор Microsoft при обработке макроса BAR внутренне не расширяет макрос BAZ до параметров, которые могут использоваться как два отдельных параметра для макроса FOO.

В соответствии со стандартом, какой компилятор правильно справляется с ситуацией?

Ответ 1

В соответствии с 16.3.4 стандарта ISO/IEC 14882: 2003 (С++ Stardard) макрораспределение выполняется следующим образом:

  • Вызов макроса заменяется списком замены макроса (тело), ​​где каждое имя параметра (если оно не зависит от # или ##) заменяется полным расширением макроса соответствующего аргумента, указанного в вызове макроса.
  • Результат этапа 1 повторно сканируется. Если в нем больше макросов (кроме тех, которые уже были расширены с учетом рассматриваемого текста), они разворачиваются в соответствии с той же процедурой рекурсивно.

Последовательность шагов для указанного вами кода:

  • BAR(BAZ)
  • FOO(3,7,1)
  • ((3)*(7)*(1))

Итак, GCC прав, а VC - нет. Но ошибка, о которой жалуется VC, заключается в том, что FOO имеет 3 аргумента, а BAR указывает только 2 из них. VC, по-видимому, пытается поймать ошибки как можно скорее и немного заходит в нее.