Как правильно добавить шестнадцатеричные escape-последовательности в строковый литерал?
Когда у вас есть строка в C, вы можете добавить внутренний шестнадцатеричный код внутри.
char str[] = "abcde"; // 'a', 'b', 'c', 'd', 'e', 0x00
char str2[] = "abc\x12\x34"; // 'a', 'b', 'c', 0x12, 0x34, 0x00
Оба примера имеют 6 байтов в памяти. Теперь проблема существует, если вы хотите добавить значение [a-fA-F0-9]
после шестнадцатеричной записи.
//I want: 'a', 'b', 'c', 0x12, 'e', 0x00
//Error, hex is too big because last e is treated as part of hex thus becoming 0x12e
char problem[] = "abc\x12e";
Возможное решение - заменить после определения.
//This will work, bad idea
char solution[6] = "abcde";
solution[3] = 0x12;
Это может работать, но это не удастся, если вы поместите его как const
.
//This will not work
const char solution[6] = "abcde";
solution[3] = 0x12; //Compilation error!
Как правильно вставить e
после \x12
без запуска ошибки?
Почему я спрашиваю? Если вы хотите построить строку UTF-8 как константу, вы должны использовать шестнадцатеричные значения символа, если она больше, чем может содержать таблица ASCII.
Ответы
Ответ 1
Используйте 3 восьмеричные цифры:
char problem[] = "abc\022e";
или разделите строку:
char problem[] = "abc\x12" "e";
Почему эти работы:
-
В отличие от шестнадцатеричных экранов, стандарт определяет 3 цифры как максимальное количество для восьмеричного выхода.
6.4.4.4 Символьные константы
...
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
...
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
-
Конкатенация строк строкой определяется как более поздняя фаза перевода, чем преобразование символа обратного символа.
5.1.1.2 Фазы перевода
...
-
Каждый элемент набора символов и escape-последовательность в символьных константах и строковые литералы преобразуются в соответствующий элемент исполнительного символа задавать; если нет соответствующего члена, он преобразуется в реализацию - определенному элементу, отличному от нулевого (широкого) символа. 8)
-
Смежные строковые литералы объединяются.
Ответ 2
Так как строковые литералы конкатенация выполняется в начале процесса компиляции, но после преобразования с экранированным символом вы можете просто использовать:
char problem[] = "abc\x12" "e";
хотя вы можете предпочесть полное разделение для удобочитаемости:
char problem[] = "abc" "\x12" "e";
Для юристов языка среди нас это описано в C11 5.1.1.2 Translation phases
(мой акцент):
-
Каждый член набора символов и escape-последовательность в символьных константах и строковых литералах преобразуется в соответствующий член набора символов выполнения; если нет соответствующего элемента, он преобразуется в определенный для реализации элемент, отличный от нулевого (широкого) символа.
-
Связанные токены литерала строки объединены.
Ответ 3
Почему я спрашиваю? Если вы хотите построить строку UTF-8 как константу, вы должны использовать шестнадцатеричные значения символа, превышающие таблицу ASCII.
Ну, нет. Вам не обязательно. Начиная с C11, вы можете префикс своей константы строки u8
, которая сообщает компилятору, что литерал символа находится в UTF-8.
char solution[] = u8"no need to use hex-codes áé§µ";
(То же самое поддерживается и С++ 11, кстати)