【问题标题】:How to properly add hex escapes into a string-literal?如何正确地将十六进制转义添加到字符串文字中?
【发布时间】:2018-01-18 15:36:40
【问题描述】:

当你在 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!

如何在\x12之后正确插入e而不触发错误?


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

【问题讨论】:

标签: c c99


【解决方案1】:

由于字符串文字在编译过程的早期就被连接起来了,但是转义字符转换之后,你可以只使用:

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

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

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

对于我们当中的语言律师,C11 5.1.1.2 Translation phases(我的重点)对此进行了介绍:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 人们可能正在寻找经典 7 位 ASCII 表的不可打印字符 0 到 31。
    • @Lundin 他们不应该省略字符 0...吗?
    • @Damon C 和 C++ 是不同的语言。 C 标准不一样(我搜索了你的文本,但没有出现)。您可以使用通用字符常量,例如u8"\u12345678",因为反斜杠、u1等在源字符集中;但是,表示的 unicode 字符可能不在源字符集中。源代码只允许包含源字符集中的字符,例如可以是 7 位 ASCII(这与执行字符集无关)。
    • @Damon 这是一个 C 问题,并且存在 C 标准,实际上没有理由涉及 C++
    • 我已经做过并在我之前的评论中解释过。允许使用通用字符名称,因为包含此类内容的所有字符都在基本源字符集中,但 unicode 字符可能不在。 扩展源字符集中的内容由实现定义,可能为空。
    【解决方案3】:

    使用 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. 每个源字符集成员和字符常量中的转义序列和 字符串字面量被转换为执行字符的对应成员 放;如果没有对应的成员,则将其转换为实现- 除空(宽)字符之外的已定义成员。 8)

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

    【讨论】:

    • 第三种选择是明确地做所有事情:char solution[] = {'a', 'b', 'c', 0x12, 'e', '\0'};
    • 甚至完全抵消转义“字符串”。 "abc" "\x12" "e"; 为清楚起见。
    猜你喜欢
    • 2019-07-27
    • 2020-11-07
    • 2017-08-23
    • 2014-03-19
    • 2013-02-07
    • 2018-01-31
    • 1970-01-01
    相关资源
    最近更新 更多