【问题标题】:Why might a string literal not be a string?为什么字符串文字可能不是字符串?
【发布时间】:2020-09-25 16:53:30
【问题描述】:

我在 C 标准中关于字符串文字的这一部分苦苦挣扎,尤其是它的第二部分:

"在翻译阶段 7 中,一个字节或值为零的代码被附加到每个由一个或多个字符串文字产生的多字节字符序列。80)"


"80) 字符串文字可能不是字符串(参见 7.1.1),因为空字符可以通过 \0 转义序列嵌入其中。"

来源:ISO/IEC 9899:2018 (C18),§6.4.5/6,第 51 页

我不明白解释 - “因为空字符可以通过 \0 转义序列嵌入其中。”。


查看引用的第 7.1.1 节,关于“字符串”的定义,声明如下:

"字符串是一个连续的字符序列,以第一个空字符结尾并包括第一个空字符。"

来源:ISO/IEC 9899:2018 (C18),§7.1.1/1,第 132 页

我想过重点可能放在“can”上,字符串文字不必包含/嵌入空字符,而字符串需要.

但是我又一次问自己:如果字符串中没有以字符串结尾的空字符,如何将字符串文字用作字符串来确定字符串的结尾(字符串操作函数所必需的) )?

我现在完全是在画空白。


注意:我知道字符串文字存储在只读内存中并且不能修改,字符串是由 NUL 终止的字符序列的通用术语,可以或不能是可变的。

因此,我的问题不是:“字符串和字符串文字有什么区别?

我的问题是:

  • 为什么/如何字符串文字不是字符串?

根据我的担忧,到目前为止:

  • 字符串文字可以省略 NUL 字节是真的吗?

我想自己问这个问题,但在发布之前不久,我得到了线索。我的困惑是因为引文中的一些错位的措辞。

但我决定不删除问题的草稿,因为它可能对未来的读者有用,而是提供问答。

请随意评论和提示。


相关内容:

【问题讨论】:

  • 我会说这是文档中的一个错误——char *p = "foo\0bar"; 我们可以说p 指向一个长度为 3 的字符串; p+4 指向另一个字符串 :)
  • @pmg 确实如此。 "foo\0bar" 是包含 两个 字符串的字符串文字,因此它不是 a 字符串。是的,就是这么简单。

标签: c string null language-lawyer string-literals


【解决方案1】:

你想多了。

“字符串是一个连续的字符序列,以第一个空字符终止并包括第一个空字符。”

来源:ISO/IEC 9899:2018 (C18),§7.1.1/1,第 132 页

表示“字符串”只能延伸到第一个空字符。在 null 之后可能存在的字符不是字符串的一部分。不过

"80) 字符串文字可能不是字符串(参见 7.1.1),因为可以通过 \0 转义序列将空字符嵌入其中。”

明确字符串文字可能包含嵌入的空值。如果是这样,则字符串文字 AS A WHOLE 不是字符串——字符串只是字符串文字的前缀,直到第一个 null

【讨论】:

    【解决方案2】:

    让我们看一下 C18 §6.5.1/3 中同一部分中术语“字符串文字”的定义:

    "字符串文字是用双引号括起来的零个或多个多字节字符的序列,如"xyz""

    据此,字符串文字仅由引号中的字符组成,即裸字符串内容。它没有附加的\0。 NUL 字节稍后在翻译时附加,如 §6.5.1/6 所述:

    "在翻译阶段 7 中,一个字节或值为零的代码被附加到每个由一个或多个字符串文字产生的多字节字符序列。80)"


    举个例子:

    "foo"字符串文字,但不是字符串,因为"foo" 不包含嵌入 空字符。 p>

    "foo\0" 是一个字符串文字和一个字符串,因为文字本身在字符序列的末尾包含一个空字符。


    请注意,您无需在 字符串文字 的末尾显式插入空字符即可将其更改为 字符串。如前所述,它是在程序翻译过程中隐式附加的。

    手段,

    const char *s = "foo";
    

    等于

    const char *s = "foo\0";
    

    我承认,那句话:

    "字符串文字可能不是字符串(参见 7.1.1),因为空字符可以通过 \0 转义序列嵌入其中。"

    在上下文中有点混乱和不合逻辑。措辞更好:

    "字符串文字可能不是字符串(参见 7.1.1),因为空字符可能不是(或 不需要)通过\0 转义序列嵌入其中。"

    或者:

    "字符串文字可能不是是字符串(参见 7.1.1),因为空字符可以通过 \0 嵌入其中转义序列。"


    正如@EricPostpischil 在他的comment 中指出的那样,脚注的含义可能完全不同。

    这意味着如果 字符串字面量在其中包含一个空字符,但不是在末尾,因为它是 字符串所必需的,字符串文字不等同于字符串

    F.e.: 字符串字面量

    "foo\0bar"
    

    不是字符串,因为它包含字符串文字内的第一个空字符嵌入,但不在其末尾.

    【讨论】:

    • 你错过了,或者至少没有说清楚,一个方面。 "abc\0def" 定义的字符序列不是字符串,因为它不是由其第一个空字符终止的。 77.11 说“string 是一个连续的字符序列,以第一个空字符结尾并包括第一个空字符。”这就是脚注 80 说字符串文字可能不是字符串的原因:字符串文字可能不符合字符串以第一个空字符结尾的规则。
    • @EricPostpischil 啊,这是有道理的。我关注的是空字符本身的存在,而不是它的位置。是的,那么实际上,脚注是有道理的。我把你的意见纳入了答案。但尽管如此,我认为这个脚注不是很清楚,也不是很傻,就像这个问题很好地展示了一样。 :-)
    • @EricPostpischil 但它给了我另一个问题:"abc\0\0" 按照这个定义是字符串吗?
    • "abc\0\0" 在其第一个空字符之后有一个字符 \0,因此该字符序列不符合字符串的规则。
    猜你喜欢
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2014-11-20
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多