为什么C ++中的字符串通常以' \ 0'?结尾?

时间:2012-06-08 04:22:06

标签: c++ c string

在许多代码示例中,人们通常在创建一个新的char数组之后使用'\0'

string s = "JustAString";
char* array = new char[s.size() + 1];
strncpy(array, s.c_str(), s.size());
array[s.size()] = '\0';

我们为什么要在这里使用'\0'

5 个答案:

答案 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与空终结符的可能冗余分配相结合。 strlcpystrcpy_s旨在解决由于忽视处理此案而引起的潜在问题。

在您的特定示例中,array[s.size()] = '\0';就是这样一种冗余:由于array的大小为s.size() + 1strncpy正在复制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终止字符串时,有两种情况:

  • 在任何用法中,如果您明确记录字符串的长度和
  • 如果您使用的是某些标准库api,则会隐式向字符串添加\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,因为您不知道分配的数组中是否有垃圾数据。这也是一种很好的做法,因为在大型代码中,您可能看不到字符数组的初始化。