为什么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
结合了一个空终止符的可能的冗余分配。 strlcpy
和strcpy_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,因为您不知道数组中是否有垃圾数据。 这也是一个很好的做法,因为在大代码中,您可能看不到字符数组的初始化。