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

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

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

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

您的问题的标题引用Cstring。 C ++ std::string对象的处理方式与标准Cstring不同。 \0在使用Cstring时很重要,当我在这里使用术语string ,我指的是标准的Cstring

\0作为C中的string终止符。它被称为空字符NUL 。 它表示处理string的代码 – 标准库,也是你自己的代码 – string的结尾。 strlen是一个很好的例子,它返回一个string的长度。

当你声明一个常量string:

 const char *str = "JustAString"; 

那么\0会自动附加给你。 在其他情况下,您将像在数组示例中一样pipe理非常量string,您有时需要自己处理它。 在你的例子中使用的strncpy的文档是一个很好的例子: strncpy复制空终止字符, 除非复制整个string之前达到指定的长度。 因此,你会经常看到strncpy结合了一个空终止符的可能的冗余分配。 strlcpystrcpy_s的devise是为了解决由于忽视处理这种情况而产生的潜在问题。

在你的例子中, array[s.size()] = '\0'; 是一个这样的冗余:因为array的大小是s.size() + 1 ,而strncpy是复制s.size()字符,函数会追加\0

标准Cstring实用程序的文档将指出何时需要注意包含这样一个空终止符。 但仔细阅读文档:与strncpy ,细节很容易被忽略,导致潜在的缓冲区溢出。

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

请注意,C ++string和Cstring是不一样的。
在C ++中,string是指std :: string ,它是一个模板类,提供了很多直观的函数来处理string。
请注意,C ++ std :: string不是以\0结尾的,但是该类提供了以\0结尾的c样式string获取底层string数据的函数。

在C中,一个string是字符的集合。 这个集合通常以\0结尾。
除非使用\0这样的特殊字符,否则无法知道string何时结束。
它也被称为stringnull终止符。

当然,还有其他记账方法可以跟踪string的长度,但是使用特殊字符有两个好处:

  • 这是更直观的
  • 没有额外的开销

请注意, \0是必需的,因为大多数标准C库函数对string进行操作(假定它们已被终止)。
例如:
在使用printf()如果你有一个不是\0的string,那么printf()会一直写字符到stdout直到遇到\0 ,简而言之,它甚至可能会打印垃圾。

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

有两种情况你不需要\0终止一个string:

  • 在任何情况下,如果你明确地loggingstring的长度和
  • 如果你正在使用一些标准的库,API会隐式地添加一个\0到string。

在你的情况下,你已经有了第二种scheme为你工作。

 array[s.size()] = '\0'; 

上面的代码语句在你的例子中是多余的。

对于你的例子使用strncpy()使它无用。 strncpy() s.size()字符复制到array ,注意如果在复制string之后剩余空间,它将追加一个空终止符。 由于array的大小为s.size() + 1会自动添加\0

'\ 0'是空终止字符。 如果你的字符数组没有它,你试图做一个strcpy你会有一个缓冲区溢出。 许多function依靠它来知道什么时候需要停止读取或写入内存。

 strncpy(array, s.c_str(), s.size()); array[s.size()] = '\0'; 

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

你不应该,那第二行是浪费空间。 如果你知道如何使用它,strncpy已经添加了一个空终止符。 代码可以被重写为:

 strncpy(array, s.c_str(), s.size()+1); 

strncpy是一个奇怪的函数,它假定第一个参数是第三个参数大小的数组。 所以如果在复制string之后还剩下空间的话,它只会复制空终止符。

在这种情况下,你也可以使用memcpy(),它会稍微更有效率,虽然也许会使代码不太直观。

在C中,我们使用char(或w_char)数组来表示string,并使用特殊字符来表示string的结尾。 与Pascal相反,Pascal将string的长度存储在数组的索引0中(因此string对字符数有硬限制), 理论上对string的数量没有限制(表示为字符数组)可以在C中

C中的默认库以及其他库中的所有函数中的特殊字符都是NUL。 如果要使用依赖于string的确切长度的库函数,则必须使用NUL终止string。 你可以完全定义你自己的终止字符,但你必须明白,涉及到string(作为字符数组)的库函数可能不会像你期望的那样工作,并且会导致各种各样的错误。

在给出的代码片段中,需要明确地将终止字符设置为NUL,因为您不知道数组中是否有垃圾数据。 这也是一个很好的做法,因为在大代码中,您可能看不到字符数组的初始化。