Я столкнулся с проблемой с новым Visual C ++ в VS 2010.
У меня есть заголовок со следующими определениями:
#define STC(y) #y
#define STR(y) STC(\y)
#define NNN(y) 0##y
#define NUM(y) NNN(y)
Смысл в том, что вы можете иметь некоторую константу, например,
#define TOKEN x5A
и вы можете получить токен в виде числа или строки:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\x5A"
Это ожидаемое поведение в соответствии с правилами подстановки аргументов макросов, и до сих пор оно хорошо работало с gcc, open watcom, pellesC (lcc), Digital Mars C и Visual C ++ в VS2008 Express.
Сегодня я перекомпилировал библиотеку с VS2010 Express только для того, чтобы обнаружить, что она больше не работает! Используя новую версию, я бы получил:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\y"
Похоже, что новый препроцессор обрабатывает \y
как escape-последовательность даже внутри макротела, что является бессмысленным, поскольку escape-последовательности имеют смысл только в литеральных строках.
Я подозреваю, что это серая область стандарта ANSI, но даже если исходное поведение было предписано стандартом, MS VC ++ не совсем известен тем, что он на 100% совместим с ANSI C, поэтому я предполагаю, что придется жить с новое поведение компилятора MS.
Учитывая, что, есть ли у кого-нибудь предложения о том, как повторно реализовать исходное поведение макросов с VS2010?
EDIT: исправлен макрос NUM()
РЕДАКТИРОВАТЬ: Возможное решение
Я думаю, что нашел способ сделать это:
#define STC(y) #y
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#define STA(x,y) STC(x##y)
#define STR(y) STA(\,y)
#else
#define STR(y) STC(\y)
#endif
#define NNN(y) 0##y
#define NUM(y) NNN(y)
Теперь я получаю:
#define TOKEN x2E
NUM(TOKEN) -> 0x2E
STR(TOKEN) -> "\x2E"
Конечно, gcc жалуется на присоединение обратной косой черты к литералу (\ ## x2E
), потому что результат не является допустимым символом препроцессора, но MS выглядит счастливым, поэтому #ifdef
.
Я буду рад узнать, если у кого-нибудь есть лучшее решение!