std::string 可以包含嵌入的空值吗?
Posted
技术标签:
【中文标题】std::string 可以包含嵌入的空值吗?【英文标题】:Can a std::string contain embedded nulls? 【发布时间】:2011-02-20 04:57:10 【问题描述】:对于常规 C 字符串,空字符 '\0'
表示数据结束。
std::string
怎么样,我可以有一个嵌入空字符的字符串吗?
【问题讨论】:
见std::string equivalent for data with NULL characters? 【参考方案1】:是的,您可以在 std::string
中嵌入空值。
例子:
std::string s;
s.push_back('\0');
s.push_back('a');
assert(s.length() == 2);
注意:std::string
的c_str()
成员将始终将空字符附加到返回的字符缓冲区;但是,std::string
的 data()
成员可能会也可能不会将空字符附加到返回的字符缓冲区。
小心操作符+=
要注意的一件事是不要在 RHS 上使用 operator+=
和 char*
。它只会累加到空字符。
例如:
std::string s = "hello";
s += "\0world";
assert(s.length() == 5);
正确方法:
std::string s = "hello";
s += std::string("\0world", 6);
assert(s.length() == 11);
存储二进制数据更常见于使用 std::vector
通常使用std::vector
来存储任意二进制数据更为常见。
std::vector<char> buf;
buf.resize(1024);
char *p = &buf.front();
这可能更常见,因为 std::string
的 data()
和 c_str()
成员返回 const 指针,因此内存不可修改。使用 &buf.front() 你可以直接修改缓冲区的内容。
【讨论】:
在 C++9x 中,&s.front()
也是可修改的,并保证指向一个连续的缓冲区。虽然在 C++03 中没有这样的保证,但没有任何已知的 C++ 实现在实践中不成立(这也是它如此迅速地添加到 C++0x 的部分原因)。
请注意,从 C++11 开始,.c_str()
和 .data
是同义词。特别是,这意味着.data
返回的字符串必须附加一个空终止符。
@PavelMinaev:我认为“C++9x”是“C++0x”的拼写错误(在您发表评论后的一段时间内变成了 C++11)。
s.append("\0world", 6);
优于 s += std::string("\0world", 6);
【参考方案2】:
是的。 std::string 只是一个有好处的vector<char>
。
但是,请小心不要将这种野兽传递给调用.c_str()
并在 0 处停止的东西。
【讨论】:
第一个不是真的,正如我最近了解到的那样。 Vector 的交换保留了迭代器和对内容的引用,字符串不一定。 ***.com/questions/25201758/… @Notinlist:它也有不同的名称!哦,恐怖【参考方案3】:你可以,但你为什么要这样做?在 std::string 中嵌入 NUL 只是自找麻烦,因为传递 std::string 的函数很可能会使用它的 c_str() 成员,并且大多数人会假设第一个 NUL 表示字符串的结尾。因此,这不是一个好主意。另请注意,在 UTF-8 中,只有 '\0' 会导致 0,因此即使出于 i18n 目的,也没有理由嵌入 NUL。
【讨论】:
感谢您解释为什么不这样做。 不,这很愚蠢。 “不要使用std::string
的全部功能,因为您可能将c_str()
的结果传递给C 字符串函数而不传递长度”,真的吗?好吧,如果你从不这样做,你会没事的......【参考方案4】:
是的,这是有效的。
字符串中间可以有一个空字符。
但是,如果您使用中间有一个空字符的 std::string 和一个 c 字符串 在未定义的行为小镇中发挥作用 - 没有人愿意在那里!!!:
int n = strlen( strWithNullInMiddle.c_str() ); // Boom!!!
【讨论】:
strlen
将只返回第一个 null 之前的字符数。这可能是意料之外的行为,但并非未定义。以上是关于std::string 可以包含嵌入的空值吗?的主要内容,如果未能解决你的问题,请参考以下文章