2

I'm using C++14 and as per my understanding std::string in C++11 and above are terminated by null character. I'm unable to understand why the below code does not work.

string a="your";
char b[5];
for(int i=0; a[i]! ='\0';i++) 
b[i] =a[i] ;
cout<<b;

Output is: "yourul"(followed by 2 random characters)

7
  • "as per my understanding std::string in C++11 and above are terminated by null character" That's where you are wrong. a[i] for i > 4 invokes UB. Commented Nov 6, 2017 at 9:03
  • @BaummitAugen - Then this should be amended. Commented Nov 6, 2017 at 9:05
  • @BaummitAugen But shouldn't a[4] be '\0'? That's my reading of the description here: cplusplus.com/reference/string/string/operator[] Commented Nov 6, 2017 at 9:06
  • 1
    @BaummitAugen is wrong. a[a.size()] == '\0' is guaranteed by the specification. Commented Nov 6, 2017 at 9:06
  • 2
    The problem is that you are not copying the null character, not that the null character is not there. Commented Nov 6, 2017 at 9:08

2 Answers 2

6

The problem is that you don't copy the terminator to the destination array. Instead you end the loop when you encounter it (without copying it).

Without knowing the use-case or the need for the array (there seldom is any), don't use manual copying like that. If, for whatever reason you can't use e.g. a.c_str() or a.data() or even &a[0], then use strncpy instead:

strncpy(b, a.c_str(), sizeof b - 1);  // -1 to leave space for the terminator
b[sizeof b - 1] = '\0';  // And make sure string is terminated

Do note that the guarantee of an existing terminator in the std::string object depends on the C++ standard used. Before C++11 there were no guarantees that the terminator existed in the string. In practice it still did (for simplicity's sake) but there were no guarantees by the specification.

Sign up to request clarification or add additional context in comments.

6 Comments

Can you use sizeof operator without parens?! :o this looks nasty! :)
@W.F. Parenthesis are needed for type-names, not for general expressions.
b=a. c_str() ; is giving me incompatible types in assignment of 'const char*' to 'char [5]'
@VishalSharma You can't assign to an array, only copy to it.
@VishalSharma And I mean that instead of using the (temporary?) array b, use one of the access-functions directly when you think the array is needed.
|
6

So std::string does have the backwards compatibility guaranteed that the sequences returned by c_str() and data() are 0-terminated, and that s[s.size()] gives you a NUL. (Note that writing over any of these terminators is undefined behavior.)

However, your code has a different bug: the loop terminates the moment it encounters the NUL, and does not copy it over to b. So the last element of b has unspecified content, and reading it is undefined behavior.

Don't write the copy loop yourself. Use strlen or one of its variants. Or better yet, if at all possible, don't use writeable C-style strings at all.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.