字符串文字中的符号 \0 是啥意思?

Posted

技术标签:

【中文标题】字符串文字中的符号 \\0 是啥意思?【英文标题】:What does the symbol \0 mean in a string-literal?字符串文字中的符号 \0 是什么意思? 【发布时间】:2011-06-10 07:59:58 【问题描述】:

考虑以下代码:

char str[] = "Hello\0";

str 数组的长度是多少,以多少个 0 结尾?

【问题讨论】:

@Ashot Martirosyan:您是否也需要了解 C,还是只对 C++ 的答案感兴趣? @Charles Bailey 我主要使用 C++,但我当然想知道 C 和 C++ 之间有什么区别。这就是我添加 C++ 标签的原因。 @UmmaGumma 如果你只是用C标记它,那么只知道C的人可以回答。如果您同时使用 C 和 C++ 对其进行标记,则会限制只能回复那些了解两种语言之间细微差别的人。仅当问题确实需要该级别的知识和专业知识时才应使用两种语言标记某些内容 - 了解两种语言之间的细微差异。 【参考方案1】:

sizeof str 是 7 - “Hello”文本的五个字节,加上显式 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)

然而,这很少有用,并且容易计算错误的字符串长度并以未终止的字符串结束。在 C++ 中也是禁止的。

【讨论】:

您应该补充一点,这种截断只在 C 中有效,在 C++ 中无效。 您的char [8] 示例似乎有误。如果 OP 使用 char str[8] = 'H', 'e', 'l', 'l', 'o', '\0', '\0' ; the remaining character's value would _not_ be undefined, it would be zero (so that you can sanely initialize, e.g. int arr[100] = 0 ` 全部为零)。我不明白为什么 "Hello\0" 与长格式有任何不同,除非标准明确为这种情况做出了例外(这对我来说似乎很奇怪。) @Chris,是的,我大概在你写回复的时候更新了它:) 顺便提一下,有问题的段落:如果大括号括起来的列表中的初始化程序少于聚合的元素或成员,或者用于初始化已知数组的字符串文字中的字符更少大小超过数组中的元素,聚合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。 仅供参考,空字符(也是空终止符),缩写为 NUL,因此术语“NUL 终止符”对我来说有点混乱。【参考方案2】:

数组长度为7,NUL字符\0仍算作一个字符,字符串仍以隐式\0结尾

查看this link 以查看工作示例

请注意,如果您将 str 声明为 char 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 */

【讨论】:

“字符串”的长度(作为 C 函数查看字符串)为 5。sizeof 运算符返回 7。 @ChrisLutz:问的问题是“str array 的长度是多少”(我的重点)所以这个答案是正确的。 @Chris 好吧,我承认C 白话对于字符串的lengthsize 有不同的含义。在我的回答中,我指的是后者。【参考方案3】:

具体来说,我想提一种情况,您可能会对此感到困惑。

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

答案是"\0"在数组中表示的是0 0""0

因为"\0" 仍然是一个字符串字面量,它还会在其末尾添加"\0"。而""为空还要加上"\0"

了解这一点将有助于您深入了解"\0"

【讨论】:

换句话说,empty-string 在 C 中仍然是 null-terminated【参考方案4】:

敲打我惯用的JUST TRY IT鼓独奏,以下是您将来如何回答此类问题的方法:

$ 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

...省略不必要的部分...

.LC0:
    .string "Hello"
    .string ""

...

.LC1:
    .string "-->%s<--\n"

...

请注意,我用于 printf 的字符串只是 "--&gt;%s&lt;---\n",而全局字符串分为两部分:"Hello"""。 GNU 汇编器还使用隐含的NUL 字符来终止字符串,因此第一个字符串 (.LC0) 在这两个部分中的事实表明存在两个NULs。因此,该字符串有 7 个字节长。一般来说,如果你真的想知道你的编译器对某个大块代码做了什么,请将它隔离在一个像这样的虚拟示例中,并使用-S 看看它在做什么(对于 GNU——MSVC 也有一个用于汇编器输出的标志,但是我不知道它的手)。您将了解很多有关您的代码如何工作(或可能无法工作)的知识,并且您将很快得到一个 100% 保证与您正在工作的工具和环境相匹配的答案。

【讨论】:

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

str 数组的长度是多少,以多少个 0 结尾?

Let's find out:

int main() 
  char str[] = "Hello\0";
  int length = sizeof str / sizeof str[0];
  // "sizeof array" is the bytes for the whole array (must use a real array, not
  // a pointer), divide by "sizeof array[0]" (sometimes sizeof *array is used)
  // to get the number of items in the array
  printf("array length: %d\n", length);
  printf("last 3 bytes: %02x %02x %02x\n",
         str[length - 3], str[length - 2], str[length - 1]);
  return 0;

【讨论】:

【参考方案6】:
char str[]= "Hello\0";

那将是 7 个字节。

在记忆中应该是:

48 65 6C 6C 6F 00 00
H  e  l  l  o  \0 \0

编辑:

C 字符串中的 \0 符号是什么意思? 它是字符串的“结束”。一个空字符。在记忆中,它实际上是一个零。通常处理 char 数组的函数会查找该字符,因为这是消息的结尾。我会在最后举个例子。

str 数组的长度是多少? (在编辑部分之前回答) 7

它以多少个 0 结尾? 您的数组有两个零的“空格”; str[5]=str[6]='\0'=0

额外的例子: 假设您有一个打印该文本数组内容的函数。 您可以将其定义为:

char str[40];

现在,您可以更改该数组的内容(我不会详细说明如何更改),使其包含以下消息:“这只是一个打印测试” 在记忆中,你应该有类似的东西:

54 68 69 73 20 69 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

所以你打印那个 char 数组。然后你想要一条新消息。让我们说“你好”

48 65 6c 6c 6f 00 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

注意 str[5] 上的 00。这就是打印函数如何知道它实际需要发送多少,尽管向量和整个内容的实际经度。

【讨论】:

您没有回答原始问题“符号是什么意思”。请扩展您的答案以解决原始问题。 其他答案已经提到 str 是一个大小为 7 的数组,包括七年前接受的答案。为什么要再次重复(不添加任何新内容)? @Michal,你知道原来的帖子有 3 个问题,对吧? @melpomene。我为此道歉。我扩展了答案,希望它能进一步澄清并添加更多,如您所愿。【参考方案7】:

'\0' 被称为 NULL 字符或 NULL 终止符 它是整数 0(零)的等价字符,因为它不代表任何内容

在 C 语言中,它通常用于标记字符串的结尾。 示例字符串 a="Arsenic"; 每个字符都存储在一个数组中

a[0]=A
a[1]=r
a[2]=s
a[3]=e
a[4]=n
a[5]=i
a[6]=c

数组末尾包含''\0'来停止为字符串'a'分配数组内存。

【讨论】:

以上是关于字符串文字中的符号 \0 是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

“字面意思”这个词是啥意思?

C#中变量名前的@符号是啥意思? [复制]

全角和半角字符是啥意思呢?

CSS中的符号波浪号(〜)是啥意思[重复]

在 PATINDEX 中 = 0 是啥意思? [关闭]

java中输出函数system.out.println("a="+a);中的+是啥意思!