С и все стандарты C ++ включают в себя текст о том, что если операция stringize не может создать корректный токен строкового литерала, поведение не определено. В C ++ 11 это действительно возможно, если включить символ новой строки в необработанный строковый литерал. Но главное в стандартах всегда было.
Есть ли другой способ, которым stringize может создать UB, где UB или плохо сформированная программа еще не произошли?
Мне было бы интересно услышать о любом диалекте С или C ++ вообще. я пишу препроцессор.
Стрификация (#
) оператор только убегает \
в строковых константах. В самом деле, \
не имеет особого значения вне строковой константы, кроме как в конце строки. Следовательно, это токен предварительной обработки (C-раздел 6.4, C ++-раздел 2.5).
Следовательно, если мы имеем
#define Q(X) #X
затем
Q(\)
законный вызов: \
токен предварительной обработки, который никогда не преобразуется в токен, поэтому он действителен Но вы не можете зачеркнуть \
; это даст вам «\», который не является допустимым строковым литералом. Следовательно, поведение вышеописанного не определено.
Вот более забавный тестовый пример:
#define Q(A) #A
#define ESCAPE(c) Q(\c)
const char* new_line=ESCAPE(n);
const char* undefined_behaviour=ESCAPE(x);
Менее интересный случай неопределенной stringify — это когда параметр stringified будет слишком длинным, чтобы быть строковым литералом. (Стандарты рекомендуют, чтобы максимальный размер строкового литерала составлял не менее 65536 символов, но ничего не говорится о максимальном размере макро-аргумента, который предположительно может быть больше.)
Других решений пока нет …