如何正确地将十六进制转义添加到字符串文字中?

til*_*z0R 46 c c99

如果在C中有字符串,则可以在其中添加直接十六进制代码.

char str[] = "abcde"; // 'a', 'b', 'c', 'd', 'e', 0x00
char str2[] = "abc\x12\x34"; // 'a', 'b', 'c', 0x12, 0x34, 0x00
Run Code Online (Sandbox Code Playgroud)

两个示例在内存中都有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";
Run Code Online (Sandbox Code Playgroud)

可能的解决方案是在定义后替换.

//This will work, bad idea
char solution[6] = "abcde";
solution[3] = 0x12;
Run Code Online (Sandbox Code Playgroud)

这可以工作,但如果你把它作为,它将失败const.

//This will not work
const char solution[6] = "abcde";
solution[3] = 0x12; //Compilation error!
Run Code Online (Sandbox Code Playgroud)

如何e\x12没有触发错误的情况下正确插入?


我为什么这么问?如果要将UTF-8字符串构建为常量,则必须使用字符的十六进制值(如果它大于ASCII表可以容纳的字符值).

use*_*733 54

使用3个八进制数字:

char problem[] = "abc\022e";
Run Code Online (Sandbox Code Playgroud)

或拆分你的字符串:

char problem[] = "abc\x12" "e";
Run Code Online (Sandbox Code Playgroud)

为什么这些工作:

  • 与十六进制转义不同,标准定义了3位数作为八进制转义的最大数量.

    6.4.4.4字符常量

    ...

    octal-escape-sequence:
        \ octal-digit
        \ octal-digit octal-digit
        \ octal-digit octal-digit octal-digit
    
    Run Code Online (Sandbox Code Playgroud)

    ...

    hexadecimal-escape-sequence:
        \x hexadecimal-digit
        hexadecimal-escape-sequence hexadecimal-digit
    
    Run Code Online (Sandbox Code Playgroud)
  • 字符串文字串联被定义为比文字转义字符转换更晚的转换阶段.

    5.1.1.2翻译阶段

    ...

    1. 字符常量和字符串文字中的每个源字符集成员和转义序列都将转换为执行字符集的相应成员; 如果没有相应的成员,则将其转换为除null(宽)字符以外的实现定义的成员.8)

    2. 相邻的字符串文字标记是连接的.

  • 第三种选择是明确地做所有事情:`char solution [] = {'a','b','c',0x12,'e','\ 0'};` (9认同)
  • 甚至完全抵消逃脱"字符串".`"abc""\ x12""e";`为清楚起见. (4认同)

pax*_*blo 20

由于字符串文字在编译过程的早期是连接的,但转义字符转换后,您可以使用:

char problem[] = "abc\x12" "e";
Run Code Online (Sandbox Code Playgroud)

虽然您可能更喜欢完全分离以提高可读性:

char problem[] = "abc" "\x12" "e";
Run Code Online (Sandbox Code Playgroud)

对于我们中间的语言律师,C11 5.1.1.2 Translation phases我的重点是:

  1. 字符常量和字符串文字中的每个源字符集成员和转义序列都将转换为执行字符集的相应成员; 如果没有相应的成员,则将其转换为除null(宽)字符以外的实现定义的成员.

  2. 相邻的字符串文字标记是连接的.


Dam*_*mon 5

我为什么要问?当您想将 UTF-8 字符串构建为常量时,您必须使用大于 ASCII 表可以容纳的字符的十六进制值。

嗯,不。你并不需要。从 C11 开始,您可以在字符串常量前加上u8,这会告诉编译器字符文字是 UTF-8。

char solution[] = u8"no need to use hex-codes áé§µ";
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,C++11 也支持同样的事情)

  • 人们可能正在寻找经典 7 位 ASCII 表的不可打印字符 0 到 31。 (3认同)