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

Как правильно добавить шестнадцатеричные 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.

4b9b3361

Ответ 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 Фазы перевода

    ...

    1. Каждый элемент набора символов и escape-последовательность в символьных константах и строковые литералы преобразуются в соответствующий элемент исполнительного символа задавать; если нет соответствующего члена, он преобразуется в реализацию - определенному элементу, отличному от нулевого (широкого) символа. 8)

    2. Смежные строковые литералы объединяются.

Ответ 2

Так как строковые литералы конкатенация выполняется в начале процесса компиляции, но после преобразования с экранированным символом вы можете просто использовать:

char problem[] = "abc\x12" "e";

хотя вы можете предпочесть полное разделение для удобочитаемости:

char problem[] = "abc" "\x12" "e";

Для юристов языка среди нас это описано в C11 5.1.1.2 Translation phases (мой акцент):

  1. Каждый член набора символов и escape-последовательность в символьных константах и ​​ строковых литералах преобразуется в соответствующий член набора символов выполнения; если нет соответствующего элемента, он преобразуется в определенный для реализации элемент, отличный от нулевого (широкого) символа.

  2. Связанные токены литерала строки объединены.

Ответ 3

Почему я спрашиваю? Если вы хотите построить строку UTF-8 как константу, вы должны использовать шестнадцатеричные значения символа, превышающие таблицу ASCII.

Ну, нет. Вам не обязательно. Начиная с C11, вы можете префикс своей константы строки u8, которая сообщает компилятору, что литерал символа находится в UTF-8.

char solution[] = u8"no need to use hex-codes á駵";

(То же самое поддерживается и С++ 11, кстати)