Неизвестный мета-символ в строковом литерале C / C ++?
-
13-09-2019 - |
Вопрос
Я создал новый проект со следующим сегментом кода:
char* strange = "(Strange??)";
cout << strange << endl;
в результате получается следующий результат:
(Странно]
Таким образом, переводя '??)' -> ']'
Отладка показывает, что мой строковый литерал char * на самом деле является этим значением, и это не потоковый перевод.Очевидно, что это не та последовательность метасимволов, которую я когда-либо видел.Возможно, какая-то последовательность символов в Юникоде или wide char?Однако я так не думаю...Я пытался отключить все связанные настройки проекта, но безрезультатно.
У кого-нибудь есть объяснение?
- Поиск :'вопросительный знак, вопросительный знак, закрывающая фигурная скобка' строковый литерал c c ++
Решение
То, что вы видите, называется триграф.
В письменной речи взрослых одного вопросительного знака достаточно для любой ситуации.Не используйте более одного одновременно, и вы никогда больше этого не увидите.
GCC по умолчанию игнорирует триграфы, потому что вряд ли кто-то использует их намеренно.Включите их с помощью -trigraph
или сообщите компилятору, чтобы он предупредил вас о них с помощью -Wtrigraphs
вариант.
Visual C++ 2010 также отключает их по умолчанию и предлагает /Zc:trigraphs
чтобы включить их.Я не могу найти ничего о способах их включения или отключения в предыдущих версиях.
Другие советы
Простой способ избежать неожиданности с триграфом:разделите строковый литерал "??" на две части:
char* strange = "(Strange??)";
char* strange2 = "(Strange?" "?)";
/* ^^^ no punctuation */
Редактировать
у gcc есть возможность предупреждать о триграфах: -Wtrigraphs
(включено с помощью -Wall
также)
окончательная правка
Цитаты из Стандарта
5.2.1.1 Trigraph sequences 1 Before any other processing takes place, each occurrence of one of the following sequences of three characters (called trigraph sequences13)) is replaced with the corresponding single character. ??= # ??) ] ??! | ??( [ ??' ^ ??> } ??/ \ ??< { ??- ~ No other trigraph sequences exist. Each ? that does not begin one of the trigraphs listed above is not changed.
5.1.1.2 Translation phases 1 The precedence among the syntax rules of translation is specified by the following phases. 1. Physical source file multibyte characters are mapped, in an implementation-defined manner, to the source character set (introducing new-line characters for end-of-line indicators) if necessary. Trigraph sequences are replaced by corresponding single-character internal representations.
Это Триграф!
??) это триграф.
Это триграф поддерживать.Вы можете предотвратить интерпретацию триграфа, экранируя любой из символов:
char* strange = "(Strange?\?)";
Это триграф.
Триграфы являются причиной.Разговор о C в статье применим и к C++.
Как уже упоминалось несколько раз, вас укусил триграф.Смотрите этот предыдущий вопрос SO для получения дополнительной информации:
Вы можете устранить проблему, используя управляющую последовательность '\?' для символа '?':
char* strange = "(Strange\?\?)";
На самом деле, это причина той escape-последовательности, которая выглядит несколько загадочно, если вы не знаете об этих чертовых триграфах.
При попытке кросс-компиляции в GCC моя последовательность воспринималась как триграф:
Так что все, что мне нужно сделать сейчас, это выяснить, как отключить это в проектах по умолчанию, поскольку я вижу, что это только создает проблемы для меня.(В любом случае я использую американскую раскладку клавиатуры)
Поведение по умолчанию в GCC — игнорировать, но выдавать предупреждение, что гораздо более разумно и действительно, насколько мне известно, Visual Studio 2010 примет его в качестве стандарта.