C++ 答案是:“;字符串可以容纳'\0';“字符”;是故意的吗?

C++ 答案是:“;字符串可以容纳'\0';“字符”;是故意的吗?,c++,standards,C++,Standards,std::string实际上可以容纳'\0'字符这一事实一直存在。这当然与C风格的字符串不一致 所以我想知道,这是出于设计,还是遗漏,还是仅仅因为标准没有禁止它,编译器允许这种情况发生?标准没有说在std::string的情况下,'\0'是任何特殊字符。因此,std::string的任何兼容实现都不应将'\0'视为任何特殊字符。当然,除非const char*被传递给字符串的成员函数,该函数被假定为以null结尾。有一组函数接受“char*”参数,并假定字符串以零结尾。如果仔细使用它们,肯定会有

std::string
实际上可以容纳
'\0'
字符这一事实一直存在。这当然与C风格的字符串不一致


所以我想知道,这是出于设计,还是遗漏,还是仅仅因为标准没有禁止它,编译器允许这种情况发生?

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

有一组函数接受“char*”参数,并假定字符串以零结尾。如果仔细使用它们,肯定会有0的字符串


相反,STL字符串故意允许零字节,因为它们不使用0来终止。所以你的问题的简单答案是,‘是的,是有意的’

我想知道你的争吵是什么<代码>“\0”只是另一个字符。在通用“char”字符串中,没有有效的方法禁止它。 不幸的是,同一个字符在C语言中有特殊的含义,但一旦您与遗留代码进行交互操作,就必须将其作为遗留代码施加的每个限制来处理

只要您坚持只使用
std::string
的代码,这就不应该成为问题

为了回应您的评论,我们需要查看在n3242中采用
21.4.2 9/10
basic_字符串(const charT*s,const Allocator&a=Allocator())的构造函数。它表示内部字符串的大小是通过
traits::length(s)
确定的,在
std::string
的情况下,它是
strlen
,要求其参数以null结尾。因此,是的,如果您试图从
常量char*
构造
std::string
,它需要以空结尾。

设计

C也可以有不以null结尾的字符串:

char sFoo[4];
strncpy(sFoo,"Test",sizeof(sFoo));
其中,
sFoo
保存以非空结尾的字符串

它有以Null结尾的字符串,可以有0

struct String {
  char *str;
  size_t length;
  size_t capacity;
};
字符串文字以NUL结尾,但并不总是引用字符串

因此,以NUL结尾的字符串是一种实践,但它确实意味着0是无效字符。

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

实际上,
strncpy
strncat
是非常不同的:

strncpy
将“NUL填充的n字节字符串”写入n字节缓冲区:长度l最多为n的字符串,以便最后的n-l字节填充NUL。注意复数:最后的所有字节都是零,注意只有一个。还要注意,l的最大允许值实际上是n,因此可以有零个NUL字节:缓冲区可能不包含以NUL结尾的字符串。(GCC有一个不可移植的函数来测量这种“NUL填充的n字节字符串”:
strnlen

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

这种差异给C初学者甚至非初学者带来了很多困惑。我甚至看到过讲授“安全C编程”的课程和书籍,这些课程和书籍混淆了有关这些标准函数的信息,并与这些信息相矛盾

这些所谓的“安全”C字符串操作函数(“代码>strn*
”系列)在C“安全编程”社区中受到了极大的批评,并且已经发明了设计更好(但非标准)的替代方法(尤其是“
strl*
”系列:
strlcpy
…)

总结:

  • strncpy
    将在有空间的情况下附加一个空终止符
  • strncat
    将始终附加空终止符

但是。。。以null结尾的字符串是C样式的字符串。或者,如果你愿意的话。当然,C中的
char*
可以指向包含空字节的缓冲区,但该缓冲区不能称为C字符串。我认为C样式的字符串与“字符串”不一致\“0”是一个有效字符,使用它作为终止符会导致元素数组的奇异行为,其中256的集合中的一个特定值被排除。就我个人而言,我认为使用空终止符是99.9%的U**x“应用程序”使用基于文本的解释性bash脚本的原因。如果字符串在data@Martin:right on中提前被空终止,开发人员害怕使用编译代码。不允许一些随意的角色是一种怪癖,而不是相反。我想我没有正确地表达这一点。我想我要问的是
std::string
是否与终止的字符串一起工作(不必以NUL结尾),或者根本不关心。此外,函数
c_str()
生成一个以null结尾的字符串,其中null是任何字符类型的值初始化的结果。@Potatoswatter是整个以null结尾的字符串的抽象。从来没有这样想过。请看C,其他人也这么想:)也就是说,
strncpy
strncat
等如果有空间,将附加一个空终止符。@KerrekSB这些函数是不同的。看看我的答案。