在许多代码示例中,人们通常在创建一个新的char数组之后使用'\0'
:
string s = "JustAString";
char* array = new char[s.size() + 1];
strncpy(array, s.c_str(), s.size());
array[s.size()] = '\0';
我们为什么要在这里使用'\0'
?
答案 0 :(得分:42)
您的问题标题引用了C字符串。 C ++ std::string
对象的处理方式与标准C 字符串不同。使用C字符串时\0
很重要,当我在这里使用术语string
时,我指的是标准C字符串。
\0
在C中充当字符串终止符。它被称为 null字符或 NUL 。它表示处理字符串的代码 - 标准库以及您自己的代码 - 字符串的结尾。一个很好的例子是strlen
,它返回一个字符串的长度。
使用:
声明常量字符串时const char *str = "JustAString";
然后会自动附加\0
。在其他情况下,您将使用数组示例管理非常量字符串,有时您需要自己处理它。您的示例中使用的docs for strncpy是一个很好的例子:strncpy
复制空终止字符除了,如果在整个指定长度之前达到字符串被复制。因此,您经常会看到strncpy
与空终结符的可能冗余分配相结合。 strlcpy
和strcpy_s
旨在解决由于忽视处理此案而引起的潜在问题。
在您的特定示例中,array[s.size()] = '\0';
就是这样一种冗余:由于array
的大小为s.size() + 1
,strncpy
正在复制s.size()
个字符,因此将附加\0
。
标准C字符串实用程序的文档将指示何时需要小心包含此类null终止符。但仔细阅读文档:与strncpy
一样,细节很容易被忽略,导致潜在的缓冲区溢出。
答案 1 :(得分:13)
为什么C ++中的字符串通常以
'\0'
终止?
请注意,C ++字符串和C字符串不相同
在C ++中,字符串是指 std::string ,它是一个模板类,并提供了许多直观的函数来处理字符串。
请注意,C ++ std :: string不是\0
终止的,但是该类提供了以\0
终止的c样式字符串来获取底层字符串数据的函数。
在C中,字符串是字符集合。此集合通常以\0
结尾
除非使用像\0
这样的特殊字符,否则无法知道字符串何时结束
它也恰如其分地称为字符串null终止符。
当然,可能还有其他记账方式来跟踪字符串的长度,但使用特殊字符有两个直接的优点:
请注意,\0
是必需的,因为大多数标准C库函数都在字符串上运行,假设它们被\0
终止。
例如:
使用printf()
时,如果您的字符串不是\0
,则printf()
会一直将字符写入stdout
,直到遇到\0
为止,简而言之甚至打印垃圾。
我们为什么要在这里使用
'\0'
?
当您不需要\0
终止字符串时,有两种情况:
\0
。 在您的情况下,您已经有第二种方案适合您。
array[s.size()] = '\0';
上面的代码语句在您的示例中是多余的。
对于使用strncpy()
的示例,它会变得毫无用处。 strncpy()
将s.size()
个字符复制到array
,请注意,如果复制字符串后还有空格,则会附加空终止。由于array
的大小为s.size() + 1
,因此会自动添加\0
。
答案 2 :(得分:6)
'\ 0'是空终止字符。如果您的字符数组没有它并且您尝试执行strcpy,则会出现缓冲区溢出。许多函数依赖于它来知道何时需要停止读取或写入内存。
答案 3 :(得分:4)
strncpy(array, s.c_str(), s.size());
array[s.size()] = '\0';
我们为什么要在这里使用'\ 0'?
你不应该,第二行浪费空间。如果你知道如何使用它,strncpy已经添加了一个空终止。代码可以重写为:
strncpy(array, s.c_str(), s.size()+1);
strncpy是一种奇怪的函数,它假设第一个参数是第三个参数大小的数组。因此,如果复制字符串后还有剩余空间,则只复制空终止。
在这种情况下你也可以使用memcpy(),它会稍微提高效率,但可能会使代码不那么直观。
答案 4 :(得分:2)
在C中,我们用char(或w_char)数组表示字符串,并使用特殊字符来表示字符串的结尾。与Pascal相反,Pascal将字符串的长度存储在数组的索引0中(因此字符串对字符数有硬性限制),理论上 对数量没有限制字符串(表示为字符数组)可以在C中使用的字符。
特殊字符应该是C中默认库的所有函数中的NUL,以及其他库。如果要使用依赖于字符串的确切长度的库函数,则必须使用NUL终止字符串。您可以完全定义自己的终止字符,但是您必须了解涉及字符串(作为字符数组)的库函数可能无法正常工作,并且会导致各种错误。
在给出的代码片段中,需要将终止字符显式设置为NUL,因为您不知道分配的数组中是否有垃圾数据。这也是一种很好的做法,因为在大型代码中,您可能看不到字符数组的初始化。