Макросы препроцессора как параметры других макросов
Следующий код C++ компилируется и работает как программист, предназначенный для 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 C++ Express 2010:
main.cpp (7): предупреждение C4003: недостаточно фактических параметров для макроса 'FOO'
main.cpp (7): ошибка C2059: синтаксическая ошибка: ')'
Похоже, проблема заключается в том, что компилятор Microsoft при внутренней обработке макроса BAR не расширяет макрос BAZ до параметров, которые можно использовать как два отдельных параметра для макроса FOO.
Согласно стандарту, какой компилятор правильно обрабатывает ситуацию?
1 ответ
В соответствии с 16.3.4 ИСО / МЭК 14882:2003 (C++ Stardard) расширение макроса выполняется следующим образом:
- Вызов макроса заменяется списком замены макроса (телом), где каждое имя параметра (если на него не влияет # или ##) заменяется полным раскрытием макроса соответствующего аргумента, указанного в вызове макроса.
- Результат шага 1 повторно проверяется. Если в нем больше вызовов макросов (кроме тех, которые уже были расширены с получением рассматриваемого текста), они расширяются в соответствии с той же процедурой рекурсивно.
Последовательность шагов для указанного вами кода:
BAR(BAZ)
FOO(3,7,1)
((3)*(7)*(1))
Так что GCC прав, а ВК нет. Но ошибка, на которую жалуется ВК, заключается в том, что FOO
имеет 3 аргумента и BAR
указывает только 2 из них. VC, по-видимому, пытается перехватить ошибки как можно скорее и заходит слишком далеко.