Ответ 1
gcc 4.7.1 является правильным. Согласно стандарту,
2.2 Фазы перевода [lex.phases]
1 - приоритет среди синтаксических правил перевода определяется следующим фазы. [...]
3. Исходный файл разбивается на токены предварительной обработки (2.5) и последовательности символов пробела (включая комментарии). [...]
4. Выполняются предпроцессорные директивы, макро-вызовы расширяются, [...]
И за 2,5 токены препроцессора [lex.pptoken], определяемый пользователем-string-literal - это маркерная обработка предварительной обработки:
2.14.8 Определенные пользователем литералы [lex.ext]
пользователя де определенно строка литерал:
string-literal ud-suffix
уд-суффикс:
Идентификатор
Таким образом, макрораспределение фазы PRId64
не имеет значения, так как "%"PRId64
уже анализируется как один токен предварительной обработки, заданный пользователем, - строковый литерал "%"
и ud-suffix PRId64
.
О, это будет потрясающе; каждый должен будет изменить
printf("%"PRId64"\n", val);
к
printf("%" PRId64"\n", val); // note extra space
Однако! gcc и clang согласились обрабатывать пользовательские строковые литералы без основного подчеркивания в суффиксе в виде двух отдельных токенов (по критерию неравномерности), см. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52538, поэтому для будущих версий gcc (я думаю, 4,8 ветка) существующий код снова будет работать.