|
|
| const char *? -- more n00bisms |
|
Michael Jensen
Member #2,870
October 2002
|
how do you give a char* back from a function? right now, I'm building a string, and returning .c_str() -- but the string is disposed as the function ends, and c_str comes back as garbage. I could malloc the data myself, but I don't want the end-programmer to have to free it. I could declare a "static char msg[8000];" or something in my class, but that's kind of ineffecient, and allows my classes memory to get mangled if the end-programmer wanted to mangle it. How does this const work in regards to this? does it solve my problem? How do I use it?
|
|
TeamTerradactyl
Member #7,733
September 2006
|
If you create a std::string inside of your function, and then you return its .c_str(), you should simply be able to use: const char *theFunction(void) { string myString; myString = "Groovy, baby!"; return (myString.c_str()); } That will copy "myString" into a specific address, which you will be able to address when the function returns. However, I'm not certain if simply <b>char theFunction() would work or if you need to declare the <b>char pointer a const: <b>const char theFunction().
|
|
Milan Mimica
Member #3,877
September 2003
|
You're returning a pointer to the member of the locally instanced class. The object will be deleted on function exit and so will object members. That won't work. There is nothing wrong if the end-programmer has to free() the returned memory. Just document that.
-- |
|
TeamTerradactyl
Member #7,733
September 2006
|
Well, if you want to do it that way... char *theFunction(void) { string myString = "Groovy!"; char *theResult = new char[myString.size()]; return theResult; } This results in a new without the matching delete, so like Milan said, you'd have to document that the end-programmer will have to free that memory.
|
|
Michael Jensen
Member #2,870
October 2002
|
tt, as milan says, your first example doesn't work -- it's what I tried, then I realized what was happening, not good. The second example, yeah, I could allocate it and return it, but that kind of sucks... oh well, maybe I'll just use a private static member.
|
|
Milan Mimica
Member #3,877
September 2003
|
Heh, not quite. You're returning an uninitialized memory block. Here is the right way to do this dumb function: char *theFunction(void) { std::string myString = "Groovy!"; return strdup(myString.c_str()); } Now you have to free() the memory. It is important to note whether to use free() or delete to free the memory. IMO, the better way to do it is to avoid C strings at all, if possible.
-- |
|
Runesabre
Member #7,573
August 2006
|
Does it have to return a value? If not, you could try: void theFunction(string& thestring) { thestring = "Groovy, baby!"; } Or perhaps... const char* theFunction(string& thestring) { thestring = "Groovy, baby!"; return thestring.c_str(); } Declaring a static can work for certain situations but will produce invalid results if the return value changes for multiple callers: const char* theFunction(void) { static string thestring = "Groovy, baby!"; return thestring.c_str(); }
_______________ |
|
Michael Jensen
Member #2,870
October 2002
|
Quote: Heh, not quite. You're returning an uninitialized memory block. It was just an example... anyway strdup is easier. What I've decided to do, is that the class will keep an internal pointer to the string it returns, and upon disopsale, or a request for a new string, it frees the old one. edit: Yeah, it has to return it, I'm attempting to write a virtual function that overloads a base class function (unsucessfully) -- or I'd just return a string. I do like that static version though. edit: ack, all bad -- all bad. -- multiple callers == death.
|
|
Milan Mimica
Member #3,877
September 2003
|
Your class can keep a std::string so that you don't have to bother with realocating the string. You just return .c_str() of the internal string.
-- |
|
Michael Jensen
Member #2,870
October 2002
|
Quote: Your class can keep a std::string so that you don't have to bother with realocating the string. You just return .c_str() of the internal string. :: smacks forehead ::
|
|
Kibiz0r
Member #6,203
September 2005
|
Or you can always use std::strings and only convert to c-style strings when you really need to... --- |
|
Goalie Ca
Member #2,579
July 2002
|
In standard c++ there is a type of pointer that knows who owns it and when it can delete itself (when the owner goes out of scope). It is called auto_ptr. Note: there can only be one owner at a time. Otherwise it works like a regular pointer. http://www.gotw.ca/publications/using_auto_ptr_effectively.htm ------------- |
|
Michael Jensen
Member #2,870
October 2002
|
Quote: Or you can always use std::strings and only convert to c-style strings when you really need to... but that's what I AM doing. auto pointers you say? I'll have to take a look at that.
|
|
ImLeftFooted
Member #3,935
October 2003
|
The solution to this problem is to stop using MSVC and start using GCC. MSVC just sucks like that. |
|
Michael Jensen
Member #2,870
October 2002
|
Quote: The solution to this problem is to stop using MSVC and start using GCC. MSVC just sucks like that. I use both -- the problem occurs in both also and has nothing to do with MSVC versus GCC.
|
|
ImLeftFooted
Member #3,935
October 2003
|
Assuming above is the issue you're talking about I've run into it and dealt with it. In my tests MSVC seems to print out garbage, while gcc does what you'd hope for. Possibly you tried this on a version of gcc more immature then mine? I'm using gcc version 3.4.2 (mingw-special) **Fixed print_r to be printf (man I've done too much php coding lately :o ). On a complete tangent, I've found this issue very annoying: int i; istringstream("5") >> i; printf("%d", i);
Earlier versions of gcc can't handle this code.. The workaround is to name the instance of istringstream. I find this work-around very ugly |
|
Milan Mimica
Member #3,877
September 2003
|
Quote: buf[255] = 0; try buf[255] = '\0'; edited: replaced / with \. EDIT (again): I see, that's not the issue here.
-- |
|
ImLeftFooted
Member #3,935
October 2003
|
Thats exactly the same, but requires three extra hard to reach key strokes. Quote: EDIT (again): I see, that's not the issue here. Yeah thats just a check so MSVC doesn't crash when it tries to output the string. Not really the point of the excerise, just a cleaning operation. Below, Baf said:
4? I only count 3 extra strokes.
You post too fast |
|
BAF
Member #2,981
December 2002
|
4? I only count 3 extra strokes. |
|
Milan Mimica
Member #3,877
September 2003
|
So the problem is that sprintf() doesn't put '\0' at the end, or is printf() ignoring it for some reason?
-- |
|
ImLeftFooted
Member #3,935
October 2003
|
The issue up for debate is what string("test").c_str() Gives you. GCC is proclaimed to give you what you'd hope for. MSVC is proclaimed to give you garbage data. |
|
BAF
Member #2,981
December 2002
|
You should use snprintf anyway. But I guess that setting the last thing to zero is a fix in case you overflow the string or hit the end, or something. I vaguely recall having to do something similar at one time, but I've since moved to less primitive, more civilized languages, so I forgot why I had to do such an ugly thing. [edit] |
|
Milan Mimica
Member #3,877
September 2003
|
what was i thinking
-- |
|
ImLeftFooted
Member #3,935
October 2003
|
Quote: Why would you want to have something like that? If it was anonymous, it could go out of scope at anytime, leaving that c_str() dangling. Clean code can handle possible situations it will go into. In this respect GCC's string::c_str has cleaner code then MSVC's string::c_str as far as handling edge cases goes. Things like this make me like GCC better then MSVC. You'd think this is a rarely used edge case, but I use this functionality all the time. |
|
Goalie Ca
Member #2,579
July 2002
|
Aah when digging around in the c++ reference i noticed something. .c_str() returns a null terminated c-string version. It does not need to be "freed" it says. See the difference? .data's is not likely to go out of scope (unless the string resizes and gets moved around in memory). I wonder how much work it would be to make these thread safe and if that factored into the decision to have a seperate c_str() from data(). Clearly these differences give flexibility to implementation. Microsoft must've interpreted a standard in the microsoft way again. ------------- |
|
|
|