Неизвестный мета-символ в строковом литерале C / C++?

Я создал новый проект с следующий фрагмент кода:

char* strange = "(Strange??)";
cout << strange << endl;

в результате получается следующий вывод:

(странно]

переводами??)' ->']'

отладка показывает, что мой строковый литерал char* на самом деле является этим значением, и это не потоковый перевод. Это, очевидно, не мета-символ последовательности, которую я видел. Возможно, какая-то последовательность Unicode или wide char? Однако я так не думаю... Я пытался отключить все связанные настройки проекта безрезультатно.

У кого-нибудь есть объяснение?

  • поиск : "вопросительный знак, знак вопроса, закрыть скобку" C C++ string literal

9 ответов


то, что вы видите, называется trigraph.

в письменном языке взрослых достаточно одного вопросительного знака для любой ситуации. Не используйте больше одного за раз, и вы никогда не увидите это снова.

GCC игнорирует триграфы по умолчанию, потому что вряд ли кто-то использует их намеренно. Включите их с помощью -trigraph вариант, или скажите компилятору, чтобы предупредить вас о них с помощью .

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.

Это Trigraph!


??)- это trigraph.


Это trigraph поддержка. Вы можете предотвратить интерпретацию триграфа, избегая любого из символов:

char* strange = "(Strange?\?)";

Это trigraph.


Триграфов причина. Разговор о C в статье также относится к C++


Как упоминалось несколько раз, вас кусает триграф. См. этот предыдущий вопрос SO для получения дополнительной информации:

вы можете исправить проблему с помощью '\?'escape sequence for the'? характер:

char* strange = "(Strange\?\?)";

на самом деле, это причина этой последовательности побега, которая несколько загадочна, если вы не знаете об этих проклятых триграфах.


при попытке кросс-компиляции на GCC он взял мою последовательность как trigraph:

поэтому все, что мне нужно сделать сейчас, это выяснить, как отключить это в проектах по умолчанию, так как я вижу, что это создает проблемы для меня. (Я все равно использую раскладку клавиатуры в США)

поведение по умолчанию в GCC-игнорировать, но давать предупреждение, которое намного более разумно и действительно то, что Visual Studio 2010 примет в качестве стандарта, насколько я знаю.