0

In C++ 98, is this a legitimate method to cast from a string to a char *?

char * n = (char *) someString.c_str(); 

(In my original wording, the function above was recommended by a senior programmer)

Namely, is it a better method than:

s2 = (char *)alloca(s0.size() + 1); memcpy(s2, s0.c_str(), s0.size() + 1); 

(courtesy of convert string to char*)

If so, why?

Use Case:

I need to use a char*, but I don't need to alter the data after it is in the char*. I'm passing it to a display library.

I'm just looking for a short and sweet answer. Thanks!

Edit: I changed the wording to this question because it got down voted. I hope my rewording makes it a better question. I think the answers were interesting and insightful.

For the record: Anyone interested in this question, should look at all the responses. I could only pick one, but I found them all interesting.

18
  • 2
    malloc in C++ isn't great either. Just use &someString[0] in C++11 and ensure the null terminator isn't touched by whatever needs the char *. Commented Jul 29, 2014 at 23:33
  • 4
    It's not correct because c_str returns a pointer to a constant string, i.e. a string you shouldn't modify, that's what the c stands for. The same goes for the method mentioned by Chris in his comment above, it's gives you a pointer to a constant string. Commented Jul 29, 2014 at 23:35
  • 5
    "it's not wrong, as it works..." ... famous last words Commented Jul 29, 2014 at 23:36
  • @Fred you need to specify whether the function being called will modify the string or not (and if so, does it need to make the string longer or shorter) Commented Jul 29, 2014 at 23:38
  • 2
    @JoachimPileborg C++11 requires that std::string use a null-terminated buffer internally, and that c_str() returns a pointer to that. Ref . So chris's method is safe so long as the null terminator is not overwritten. Commented Jul 29, 2014 at 23:41

4 Answers 4

3

string::c_str() returns a const pointer to a null-terminated C-style string that contains the same contents as the original string. In most common implementations, c_str() simply returns a pointer to the string's internal data if it is not empty, but that is not required by the C++ standard.

If you just need to read the content of the string and not modify it, there is no need to allocate a separate buffer, just use c_str() by itself. The returned char* will remain valid as long as the string is not altered, either by the =/+=/[] operator, or the insert() or erase() method, or an iterator, etc.

If you need to modify the string via the char* pointer, then you have to allocate a separate buffer, copy the string content into it, modify it as needed, and then copy the new content back to the string using its own methods.

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

4 Comments

"...but that is not required by the C++ standard". In C++11 and later, string::c_str() will always point to the internal buffer, as it is required by the standard :-)
@KarlNicoll in C++98 I think there were vendors who put out copy-on-write strings
got it. so it will work, but from the general consensus it's in general a bad practice.
No, the general consensus is - it depends on the context in which it is being used. In a read-only context, it is perfectly safe. In a writable context, it may not be.
0

Your senior programmer is wrong. Casting away const-ness like that at the very least is wrong (no guarantees that it points to the actual memory of the string for example), and yields undefined behavior if the underlying objects happen to be const.

2 Comments

In C++11 it is guaranteed to point to the actual memory of the string, which is modifiable. And prior to C++11 it is OK to cast away constness so long as the string elements are not actually modified.
Unfortunately, we are still using C++ 99. I tried convincing them we should upgrade to C++ 11, but they don't listen. What I need to do is odd. I'm working with a gtk gchar*. There may be a better way of using gtk, but at the moment, I'm passing my data around as strings. When I need to put it to gtk, I convert it to a char*, and then into a gchar*. So I admit what I'm doing in the first place is strange, and there is probably a better way.
0

The answer here depends on whether you need a mutable string or just to be able to read it.

If all you want to do with your char* is to look at the contents then, as the comments have pointed out, you need to assign it to a const char* (and drop the cast).

Your method works, but if all you need to do is read the string, there is no point in copying it to a new location.

If you need to modify the string, then your copy would be appropriate. However, you need to be aware that changes will not be reflected in the original string.

3 Comments

thanks. All I basically just need to pass it to a function that requires a char*, and all that function will do is display the data.
@Fred: Alter the function to take a const char* if possible
thanks, I will see if there is a gtk variant for that.
0

First off, memcpy does not allocate memory. It only copies things from one place to another.

In C++ the idiom, using memcpy is:

std::string my_string = "California Needs Rain!\n"; char * p_text_string = new char [my_string.length() + 1U]; memcpy(p_text_string, my_string.c_str(), my_string.length()); // Add the nul terminator p_text_string[my_string.length()] = '\0'; 

Remember that the memory allocated needs to be 1 more than the length of the string because of the nul, '\0', terminator character that needs to be appended.

The std::string is not required to be nul terminated.

2 Comments

If you like the answer or think it helps, click on the check mark.
for the record, your answer was useful to me, but it looks like I can only pick one. Since all the answers were insightful, I picked the first one.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.