n. *_* m. 3 c c-strings null-terminated
它们与非空终止字符串有何不同?终止字符串的这个 null 是什么?和NULL有什么不同吗?我应该自己以空终止我的字符串,还是编译器会为我做这件事?为什么需要空终止字符串?如何设置代码/数据来处理空终止字符串?
什么是空终止字符串?
在 C 中,“空终止字符串”是同义反复。根据定义,字符串是连续的以 null 结尾的字符序列(数组或数组的一部分)。其他语言可能以不同的方式处理字符串。我只讨论 C 字符串。
它们与非空终止字符串有何不同?
C 中不存在非空终止字符串。非空终止字符数组只是字符数组。
终止字符串的这个 null 是什么?和NULL有什么不同吗?
“空字符”是整数值为零的字符。(字符本质上是小整数)。有时,特别是在 ASCII 上下文中,它被称为 NUL(单 L)。这与 NULL (double L) 不同,后者是空指针。空字符可以写为'\0'或仅写0在源代码中。这两种形式在 C 中可以互换(但在 C++ 中则不能)。前者通常是首选,因为它更好地表达了意图。
我应该自己以空终止我的字符串,还是编译器会为我做这件事?
如果您正在编写字符串文字,则不需要在末尾显式插入空字符。编译器会这样做。
char* str1 = "a string"; // ok, \0 is inserted automatically
char* str2 = "a string\0"; // extra \0 is not needed
Run Code Online (Sandbox Code Playgroud)
当声明具有显式大小的数组并使用字符数超出数组可容纳的字符数的字符串文字对其进行初始化时,编译器不会插入空字符。
char str3[5] = "hello"; // not enough space in the array for the null terminator
char str4[] = "hello"; // ok, there is \0 in the end, the total size is 6
Run Code Online (Sandbox Code Playgroud)
声明数组且不使用字符串文字初始化数组时,编译器不会插入空字符。
char str5[] = { 'h', 'e', 'l', 'l', 'o' }; // no null terminator
char str6[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; // null terminator
Run Code Online (Sandbox Code Playgroud)
如果您在运行时使用来自 IO 或程序不同部分的某些数据构建字符串,则需要确保插入空终止符。例如:
char* duplicate_string(const char* src)
{
char* result = malloc(strlen(src) + 1); // <- reserve place for null terminator
strcpy(dst, src);
return dst;
}
Run Code Online (Sandbox Code Playgroud)
标准库函数(例如)fread和 POSIX 函数(例如)read永远不会以 null 终止其参数。strncpy如果有足够的空间,将添加一个空终止符,因此请小心使用。令人困惑的是,strncat总是会添加一个空终止符。
为什么需要空终止字符串?
标准 C 库中的许多函数以及第三方库中的许多函数都对字符串进行操作(并且所有字符串都需要以 null 终止)。如果将非空终止字符数组传递给需要字符串的函数,则结果可能是未定义的。因此,如果您想与周围的世界进行互操作,则需要以 null 结尾的字符串。如果您从不使用任何需要字符串参数的标准库或第三方函数,您可以执行您想要的操作。
如何设置代码/数据来处理空终止字符串?
如果您计划存储长度最多为 N 的字符串,请为数据分配 N+1 个字符。空终止符所需的字符不包括在字符串的长度中,但它包括在存储它所需的数组的大小中。