考虑以下代码:
char str[] = "Hello\0";
str 数组的长度是多少,它以多少 0 结尾?
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++ 中也是禁止的。
数组长度为 7,NUL 字符\0
仍然算作一个字符,字符串仍然以隐式终止\0
请参阅此链接以查看工作示例
请注意,如果您声明长度将为 6,str
因为char str[6]= "Hello\0";
只有在它可以适合的情况下才添加隐式 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 */
具体来说,我想提一种情况,您可能会对此感到困惑。
“\0”和“”有什么区别?
答案是"\0"
在数组中表示 is{0 0}
和""
is {0}
。
因为"\0"
仍然是一个字符串文字,它也会"\0"
在它的末尾添加。而且""
是空的还要加"\0"
。
了解这一点将有助于您深入了解"\0"
。
敲打我平常的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 的字符串是如何"-->%s<---\n"
在全局字符串分为两部分时使用的:"Hello"
和""
. GNU 汇编器还使用隐式NUL
字符终止字符串,因此第一个字符串 (.LC0) 在这两个部分中的事实表明存在两个NUL
s。因此,该字符串有 7 个字节长。一般来说,如果你真的想知道你的编译器对某个大块代码做了什么,把它隔离在一个像这样的虚拟示例中,看看它在做什么-S
(对于 GNU——MSVC 也有一个用于汇编器输出的标志,但我没有'不知道它的手)。您将了解很多有关您的代码如何工作(或可能无法工作)的知识,并且您将很快得到一个 100% 保证与您正在工作的工具和环境相匹配的答案。
str 数组的长度是多少,它以多少 0 结尾?
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;
}
'\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' 分配数组内存。
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。这就是 print 函数如何知道它实际需要发送多少,尽管矢量和整个内容的实际经度。