Vishal Sharma
Vishal Sharma

Reputation: 1750

string copied to character array

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)

Upvotes: 2

Views: 81

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409472

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.

Upvotes: 6

Sebastian Redl
Sebastian Redl

Reputation: 72102

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.

Upvotes: 6

Related Questions