是:"std::string can hold '' character"设计吗?

Is the: "std::string can hold '' character" by design?

本文关键字:character can hold std string      更新时间:2023-10-16

std::string实际上可以容纳''字符的事实一直出现。这当然与c风格的字符串不一致。

所以我想知道,这是设计,还是遗漏,或者只是标准不禁止它和编译器允许这种情况发生的事实?

我不知道你们在吵什么。''只是另一个字符。在通用'char'字符串中没有有效的方法来禁止它。同样的字符在C语言中具有特殊的含义是不幸的,但是必须处理遗留代码一旦与它互操作所施加的每一个限制。

这应该不是一个问题,只要你坚持代码只使用std::string

为了解决你的评论,我们需要看一下构造函数,它接受char*,在n3242中21.4.2 9/10中的basic_string(const charT* s, const Allocator& a = Allocator())。它说内部字符串的大小是通过traits::length(s)确定的,在std::string的情况下是strlen,这要求它的参数以空结束。所以,是的,如果你试图从const char*构建一个std::string,它需要null终止。

有一组函数接受'char *'参数,并假设字符串以零结束。如果你小心地使用它们,你当然可以得到包含0的字符串。

相比之下,

STL字符串故意允许零字节,因为它们不使用0作为终止。因此,对你的问题的简单回答是:"是的,这是有意为之。"

标准没有说在std::string的情况下''是任何特殊字符。因此,任何符合std::string的实现都不应该将''视为任何特殊字符。当然,除非将const char*传递给字符串的成员函数,否则假定该字符串以null结束。

按设计。

C也可以有不以空结束的字符串:

char sFoo[4];
strncpy(sFoo,"Test",sizeof(sFoo));

sFoo保存非null终止字符串

有以null结尾的字符串可以是0,比如

struct String {
  char *str;
  size_t length;
  size_t capacity;
};

字符串字面值是NUL终止的,但这并不总是指字符串。

以NUL结尾的字符串是惯例,但这确实意味着无效字符中的0

strncpy vs. strncat

也就是说,如果有空间,strncpy和strncat等将追加一个空终止符。

实际上strncpystrncat是非常不同的:

strncpyn-bytes缓冲区写入一个"null填充的n字节字符串":一个长度l最多为n的字符串,使得最后一个n- l字节被NUL填充。注意复数:所有最后一个字节都是零,只注意一个。还要注意,l的最大允许值实际上是n,因此可以没有NUL字节:缓冲区可能不会保存以null结尾的字符串。(GCC有一个不可移植的函数来测量这种" null填充的n字节字符串":strnlen)

相反,strncat输出一个以null结尾的字符串到缓冲区。在这两种情况下,如果字符串太长,字符串将被截断,但在strncpy的情况下,n字符字符串将适合n-字节缓冲区,而在strncat的情况下,n字符的结果将只适合(n+1)-字节缓冲区。

这个差异给C初学者甚至非初学者带来了很多困惑。我甚至看到过讲授"安全的C编程"的课程和书籍,其中关于这些标准函数的信息令人困惑和矛盾。

这些所谓的"安全"C字符串操作函数("strn*"家族)在C"安全编程"社区中受到了非常多的批评,并且已经发明了更好的设计(但非标准)替代方案(特别是"strl*"家族:strlcpy…)。

概要:

  • strncpy将添加空终止符,如果有空间;
  • strncat将附加一个空终止符总是