Подтвердить что ты не робот

Когда компиляторы С++ начали рассматривать более двух шестнадцатеричных цифр в строковых литералах?

У меня есть (сгенерированная) литеральная строка на С++, которая может содержать символы, которые нужно экранировать с помощью нотации \x. Например:

char foo[] = "\xABEcho";

Однако g++ (версия 4.1.2, если это имеет значение) вызывает ошибку:

test.cpp:1: error: hex escape sequence out of range

Компилятор, по-видимому, рассматривает символы Ec как часть предыдущего шестнадцатеричного числа (поскольку они выглядят как шестнадцатеричные цифры). Поскольку четырехзначное шестнадцатеричное число не будет соответствовать значению char, возникает ошибка. Очевидно, что для широкого строкового литерала L"\xABEcho" первым символом будет U + ABEC, а затем L"ho".

Кажется, это изменилось за последние несколько десятилетий, и я никогда не замечал. Я почти уверен, что старые компиляторы C рассмотрят только две шестнадцатеричные цифры после \x и не будут выглядеть дальше.

Я могу подумать об одном обходном пути для этого:

char foo[] = "\xAB""Echo";

но это немного уродливо. Поэтому у меня есть три вопроса:

  • Когда это изменилось?

  • Почему компилятор не принимает > двухзначные шестнадцатеричные экраны для широкоформатных литералов?

  • Есть ли обходной путь, который менее неудобен, чем выше?

4b9b3361

Ответ 1

GCC только соответствует стандарту. # 877: "Каждая [...] шестнадцатеричная escape-последовательность - это самая длинная последовательность символов, которая может составлять escape-последовательность."

Ответ 2

Я нашел ответы на свои вопросы:

  • С++ всегда был таким образом (проверено третье издание Stroustrup, ранее не было). В первом выпуске K & R не упоминалось \x вообще (единственный доступ к символу, доступный в то время, был восьмеричным). K & R 2nd edition гласит:

    '\xhh'
    

    где hh - одна или несколько шестнадцатеричных цифр (0... 9, a... f, A... F).

    поэтому, похоже, это поведение было связано с ANSI C.

  • Хотя возможно, что компилятор может принимать только 2 символа для широкоформатных литералов, это излишне усложняло бы грамматику.

  • В действительности существует менее сложное обходное решение:

    char foo[] = "\u00ABEcho";
    

    Вывод \u всегда принимает четыре шестнадцатеричных цифры.

Обновить. Использование \u не совсем применимо во всех ситуациях, потому что большинство символов ASCII (по некоторым причинам) не разрешено указывать с помощью \u. Вот фрагмент из GCC:

/* The standard permits $, @ and ` to be specified as UCNs.  We use
     hex escapes so that this also works with EBCDIC hosts.  */
  else if ((result < 0xa0
            && (result != 0x24 && result != 0x40 && result != 0x60))
           || (result & 0x80000000)
           || (result >= 0xD800 && result <= 0xDFFF))
    {
      cpp_error (pfile, CPP_DL_ERROR,
                 "%.*s is not a valid universal character",
                 (int) (str - base), base);
      result = 1;
    }

Ответ 3

Я решил это, указав следующий char с \xnn тоже. К сожалению, вы должны использовать это до тех пор, пока в диапазоне [a..f] есть char. ех. "\ xnneceg" заменяется на "\ xnn\x65\x63\x65g"

Ответ 4

Я уверен, что С++ всегда был таким. В любом случае CHAR_BIT может быть больше 8, и в этом случае '\xABE' или '\xABEc' могут быть действительными.

Ответ 5

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

"Юлий C\xE6sar завоеватель frana\xE7\bais"

Ответ 6

Это широкоформатные литералы.

char foo[] = "\x00ABEcho";

Может быть, лучше.

Здесь некоторая информация, а не gcc, но все же кажется применимой.

http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.pgmgd.doc/cpprog624.htm

Эта ссылка содержит важную строку:

Задание \xnn в строковом литерале wchar_t эквивалентно заданию \x00nn

Это также может быть полезно.

http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro