什么是空终止字符串?

What are null-terminated strings?

它们与非空终止字符串有何不同?这个终止字符串的 null 是什么?它与 NULL 有什么不同?我应该自己用 null 终止我的字符串,还是编译器会为我做这件事?为什么需要以 null 结尾的字符串?如何设置我的 code/data 来处理以 null 结尾的字符串?

什么是 null-terminating 字符串?
在 C 中,“null-terminated 字符串”是重言式。字符串 by definition 是连续的 null-terminated 字符序列(数组或数组的一部分)。其他语言可能以不同方式处理字符串。我只讨论 C 字符串。

它们与非 null-terminated 字符串有何不同?
C 中没有非 null-terminated 字符串。非 null-terminated 字符数组只是一个字符数组。

终止字符串的空值是什么?它与 NULL 有什么不同? “空字符”是整数值为零的字符。 (字符本质上是小整数)。有时,特别是在 ASCII 的上下文中,它被称为 NUL(单 L)。这与 NULL (double L) 不同,后者是一个空 pointer。空字符在源代码中可以写成'[=13=]'或直接写成0。这两种形式在 C 中可以互换(但在 C++ 中不能)。通常首选前者,因为它能更好地表达意图。

我应该 null-terminate 我自己的字符串,还是编译器会为我做?
如果您正在编写字符串文字,则不需要在末尾显式插入空字符。编译器会做的。

char* str1 = "a string";   // ok, [=10=] is inserted automatically
char* str2 = "a string[=10=]"; // extra [=10=] is not needed

编译器在声明具有显式大小的数组并使用字符数超过数组可容纳的字符串文字对其进行初始化时不会插入空字符。

char str3[5] = "hello"; // not enough space in the array for the null terminator
char str4[]  = "hello"; // ok, there is [=11=] in the end, the total size is 6

编译器在声明数组时不会插入空字符,并且不会用字符串文字初始化它。

char str5[] = { 'h', 'e', 'l', 'l', 'o' };       // no null terminator
char str6[] = { 'h', 'e', 'l', 'l', 'o', '[=12=]' }; // null terminator

如果您要使用来自 IO 或程序不同部分的一些数据在 run-time 处构建字符串,您需要确保插入空终止符。标准库函数,例如 fread 和 POSIX 函数,例如 read 从不 null-terminate 它们的参数。 strncpy 如果有足够的 space 将添加一个 null-terminator,因此请谨慎使用。令人困惑的是,strncat 总是会添加一个 null-terminator.

为什么需要 null-terminated 个字符串?
标准 C 库中的许多函数以及 third-party 库中的许多函数都对字符串进行操作(并且 所有 字符串需要 null-terminated)。如果将非 null-terminated 字符数组传递给需要字符串的函数,则结果可能未定义。所以如果你想与你周围的世界互操作,你需要 null-terminated 个字符串。如果你从不使用任何需要字符串参数的 standard-library 或 third-party 函数,你可以做你想做的。

如何设置我的 code/data 来处理 null-terminated 字符串?
如果您计划存储长度最多为 N 的字符串,请为您的数据分配 N+1 个字符。空终止符所需的字符不包含在字符串的 length 中,但包含在存储它所需的数组的 size 中.