符号\ 0在字符串文字中的含义是什么?

Umm*_*mma 50 c c++ string escaping string-literals

考虑以下代码:

char str[] = "Hello\0";
Run Code Online (Sandbox Code Playgroud)

str数组的长度是多少,它的结尾是多少?

bdo*_*lan 88

sizeof str 是"Hello"文本的7 - 5个字节,加上显式NUL终止符,加上隐式NUL终止符.

strlen(str) 是5 - 仅五个"Hello"字节.

这里的关键是总是添加隐式nul终止符- 即使字符串文字恰好以\0.当然,strlen只是在第一次停止\0- 它无法区分.

隐式NUL终结符规则有一个例外 - 如果您明确指定数组大小,则字符串将被截断以适合:

char str[6] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 6 (with one NUL)
char str[7] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 7 (with two NULs)
char str[8] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 8 (with three NULs per C99 6.7.8.21)
Run Code Online (Sandbox Code Playgroud)

然而,这很少有用,并且容易错误计算字符串长度并最终导致未终止的字符串.它在C++中也是禁止的.

  • 您应该补充一点,这种截断仅在C中有效,而在C++中无效. (5认同)
  • 你的`char [8]`例子似乎错了.如果OP使用了`char str [8] = {'H','e','l','l','o','\ 0','\ 0'}; 剩下的字符值将_not_未定义,它将为零(这样你就可以灵活地初始化,例如`int arr [100] = {0}`为全零).我不明白为什么它对于`'Hello\0"`而不是长形式有什么不同,除非标准明确地为这种情况做了一个例外(这对我来说似乎很奇怪.) (3认同)

Sie*_*geX 10

数组的长度为7,NUL字符\0仍计为字符,字符串仍然以隐式终止\0

请参阅此链接以查看工作示例

注意了,你宣布,strchar str[6]= "Hello\0";长度是6,因为隐含NUL仅添加如果它能够适应(它不能在这个例子中).

§6.7.8/ p14
字符类型数组可以用字符串文字初始化,可选择用大括号括起来.字符串文字的过多字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素.

例子

char str[] = "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[5]= "Hello\0"; /* sizeof == 5, str is "Hello" with no NUL (no longer a C-string, just an array of char). This may trigger compiler warning */
char str[6]= "Hello\0"; /* sizeof == 6, Explicit NUL only */
char str[7]= "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[8]= "Hello\0"; /* sizeof == 8, Explicit + two Implicit NUL */
Run Code Online (Sandbox Code Playgroud)

  • @ChrisLutz:问的问题是"str _array_的长度是多少"(我的重点)所以这个答案是正确的. (2认同)

JUS*_*ION 5

敲打我平时鼓独奏试试吧,这里是你如何回答这样的在未来的问题:

$ cat junk.c
#include <stdio.h>

char* string = "Hello\0";

int main(int argv, char** argc)
{
    printf("-->%s<--\n", string);
}
$ gcc -S junk.c
$ cat junk.s
Run Code Online (Sandbox Code Playgroud)

......消除不必要的部分......

.LC0:
    .string "Hello"
    .string ""
Run Code Online (Sandbox Code Playgroud)

...

.LC1:
    .string "-->%s<--\n"
Run Code Online (Sandbox Code Playgroud)

...

请注意我在printf中使用"-->%s<---\n"的字符串是如何在全局字符串分为两部分的时候:"Hello""".GNU汇编器也使用隐式NUL字符终止字符串,因此第一个字符串(.LC0)在这两个部分中的事实表明有两个NULs.因此字符串长7个字节.一般来说,如果你真的想知道你的编译器在使用某些代码块时做了什么,请将它隔离在这样的虚拟示例中并查看它正在使用的内容-S(对于GNU - MSVC也有汇编器输出的标志,但我不知道我知道它是手头的).您将学到很多关于代码如何工作(或根据具体情况无法工作)的知识,并且您将快速得到一个100%保证与您正在使用的工具和环境相匹配的答案.

  • ...除非我们正在测试的东西恰好是未定义的行为,在这种情况下,答案可能只有100%保证与测试时的工具和环境相匹配.此外,如果我们测试的东西是实现定义的,那么为了真正得到答案,我们必须在所有可能的实现上测试它.(而且我们还必须*知道*它是实现定义的,但如果我们已经知道,我们就不必问了.)此外,要以这种方式进行测试,我们需要知道规则GNU汇编程序以及我们实际尝试使用的语言. (2认同)

Yon*_* Hu 5

具体来说,我想提及一种可能使您感到困惑的情况。

“ \ 0”和“”有什么区别?

答案是"\0"在数组is {0 0}""is中表示{0}

因为"\0"仍然是字符串文字,它也将添加"\0"在其末尾。并且""为空也要添加"\0"

了解这一点将帮助您深入理解"\0"

  • 换句话说,*空字符串*在 C 中仍然是*空终止*。 (2认同)