简体   繁体   English

将'\\ 0'添加到std :: string时出现意外行为

[英]Unexpected behavior on adding '\0' to std::string

Why does the C++ standard allow the following? 为什么C ++标准允许以下内容?

#include <iostream>
#include <string>    

int main()
{
    std::string s(10, '\0'); // s.length() now is 10
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    s.append(5, '\0'); // s.length() now is 15 
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    // the same with += char and push_back 

    // but:
    s += "hello"; // s.length() returns 20 string is "hello"
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;

    return 0;
}

Why does it add 0 and count it? 为什么它会加0并计算它? It looks like broken integrity of string, doesn't it? 它看起来像字符串的完整性,不是吗? But I checked standard and it is correct behavior. 但我检查标准,这是正确的行为。

Why does standard allows following? 为什么标准允许遵循?

Because the people designing C++ strings decided that such things should be allowed. 因为设计C ++字符串的人决定应该允许这样的事情。 I'm not sure if anyone that was part of the team that designed C++ strings are on SO... But since you yourself say that the standard allows it, that's the way it is, and I doubt it's about to change. 我不确定那些设计C ++字符串的团队是否属于某个人......但是既然你自己说标准允许它,那就是它的样子,我怀疑它是否会改变。

It's sometimes quite practical to have a string that can contain "anything". 拥有一个可以包含“任何东西”的字符串有时候很实用。 I can think of a few instances when I've had to work around the fact that C style strings can't contain zero-bytes. 当我不得不解决C样式字符串不能包含零字节的事实时,我可以想到一些实例。 Along with the fact that long C style strings take a long time to find the length of, the main benefit of C++ strings is that they are not restricted to "what you can put in them" - that's a good thing in my book. 除了长C风格的字符串需要很长时间才能找到它的长度之外,C ++字符串的主要好处是它们不仅限于“你可以放入它们的内容” - 这在我的书中是件好事。

Not sure what is problem here. 不知道这里有什么问题。

Adding '\\0' in the middle of the std::string changes nothing - null character is treated like any other. std::string中间添加'\\0'不会改变任何内容 - null字符被视为任何其他字符。 The only thing that can change is if you use .c_str() with function that accepts null-terminated strings. 唯一可以改变的是,如果你使用.c_str()函数接受以null结尾的字符串。 But then it's not problem of .c_str() , only with the function that treats '\\0' specially. 但是,这不是.c_str()问题,只有特殊处理'\\0'的函数。

If you want to know how many characters has this string as if treated like null-terminated string, use 如果您想知道这个字符串有多少字符就好像处理以null结尾的字符串一样,请使用

size_t len = strlen(s.c_str());

Note that it's O(n) operation, because that's how strlen works. 注意它是O(n)操作,因为这是strlen工作原理。

If you ask why += operator doesn't add the implicit null character of string literal "hello" to the string, I say the reverse (adding it) is unclear and definitely not what you want 99% of the time. 如果你问为什么+=运算符没有将字符串文字"hello"的隐式空字符添加到字符串中,我说反向(添加它)不清楚,绝对不是你想要99%的时间。 On the other hand, if you want to add '\\0' to your string, just append it like a buffer: 另一方面,如果要在字符串中添加'\\0' ,只需将其作为缓冲区附加:

char buffer[] = "Hello";
s.append(buffer, sizeof(buffer));

or (even better) drop the char arrays and null-terminated strings altogether and use C++-style replacements like std::string as NTS-replacement, std::vector<char> as contiguous buffer, std::vector as dynamic array with pointers replacement, and std::array (C++11) as standard C array replacement. 或者(甚至更好)完全删除char数组和以null结尾的字符串,并使用C ++样式替换,如std::string作为NTS替换, std::vector<char>作为连续缓冲区, std::vector作为动态数组指针替换,以及std::array (C ++ 11)作为标准C数组替换。

Also, (as mentioned by @AdamRosenfield in comments), your string after adding "hello" does have in fact 20 characters, it's probably only that your terminal doesn't print nulls. 另外,(如评论中的@AdamRosenfield所述),添加"hello"后的字符串实际上有20个字符,可能只是你的终端不打印空值。

NUL char '\\0' is the ending character for c style string , not std::string s. NUL char '\\0'c style string的结束字符,而不是std::string s。 However, it supports this character to get values from a const char pointer so that it can find the end of a c-style string. 但是,它支持此字符从const char指针获取值,以便它可以找到c样式字符串的结尾。 Otherwise, it is treated just like other characters 否则,它会像其他角色一样对待

std::string is more of a container for characters than anything else and \\0 is a character. std :: string更像是一个容器,而不是其他任何东西,\\ 0是一个字符。 As a real world example, take a look at the CreateProcess function in Windows. 作为一个真实的例子,请看一下Windows中的CreateProcess函数。 The lpEnvironment parameter takes a null-terminated block of null-terminated strings (ie A=1\\0B=2\\0C=3\\0\\0 ). lpEnvironment参数采用以null结尾的以空字符结尾的字符串块(即A=1\\0B=2\\0C=3\\0\\0 )。 If you're building a block it's convenient to use an std::string. 如果你正在构建一个块,那么使用std :: string很方便。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM