4
#include<iostream>
#include<string>
using namespace std;
int main(){
    string i = "abc\0defg";
    cout<<i<<endl;
    // This prints "abc"

    string x = "abcdefg";
    x[3]='\0';
    cout << x << endl;
    // This prints "abcefg"
}

I know that the instance i of the C++ String class doesn't interpret \0 as the end of a string. Why the string i left out everything after the \0? What's the difference between string i and x?

o_yeah
  • 688
  • 7
  • 17
  • 1
    std::string is not null terminated. https://stackoverflow.com/questions/11752705/does-stdstring-contain-null-terminator – schorsch312 Sep 21 '20 at 04:37

1 Answers1

6

The string literal "abc\0defg" is a char const [9]. std::string doesn't have a constructor that takes an array, but it can accept a char const *. So when i is used with that constructor, it thinks that the \0 inside the string indicates the end of the string (which is in fact how the end of a char const * string is usually calculated). So i only contains abc when it is constructed.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • If you want to add fun/confusion (depending on your point of view), throw in `using namespace std::string_literals;` and put an `s` at the end of the initialization, as in `string i = "abc\0defg"s;`. :) – JaMiT Sep 21 '20 at 04:40
  • 1
    _When this array is decayed to a `char const *`, it only contains `abc`._ Hmm. I would say it a bit more convoluted: A `char const*` is a pointer and it points to the address where `'a'` is stored. `abc\0defg\0` will still be there but (practically) every standard C string function will stop at the first `\0` (after `c`) if there is no option to provide the explicit length as additional argument. – Scheff's Cat Sep 21 '20 at 04:49
  • @Scheff Thanks for the tip. I tried rephrasing the answer differently. – cigien Sep 21 '20 at 04:56
  • 1
    ...and this is what happens in `std::string::string(const char*)` as well. Please, note that there is also a `std::string::string(const char*, size_t)` which could be used instead: `const char str[] = "abc\0defg"; string i(str, sizeof str - 1);` (The `- 1` is given to cut of the _second_ `\0`.) – Scheff's Cat Sep 21 '20 at 04:59
  • Thanks. Is it correct that `x` and `i` are of the same type, have the same value after `x[3]='\0';`? – o_yeah Sep 21 '20 at 05:10
  • They have the same type, but even after `x[3]='\0'`, `x` has 8 chars. – cigien Sep 21 '20 at 05:14
  • So the difference has nothing to do with `cout`. When the two strings are initialized, they are inherently different in terms of value. `i` is `abc\0` while `x` is `abcdefg\0` – o_yeah Sep 21 '20 at 05:18
  • Yes, exactly :) – cigien Sep 21 '20 at 05:19
  • Why doesn't x stop printing after it encounters null `\0`? – Mohit Sharma Sep 21 '20 at 07:28
  • 1
    @MohitSharma That's just how `string`s are printed. The `\0` is not considered the end of the `string`. – cigien Sep 21 '20 at 12:41
  • 1
    @MohitSharma You might want to try the code in the question, then change `cout << x << endl;` to `cout << x.c_str() << endl;`. If it were not for the null character, streaming a string would have the same result as streaming its `c_str()`. – JaMiT Sep 21 '20 at 21:50