I have a function
ValArgument(char* ptr){
char str[] = "hello world";
ptr = &str[0];
}
In this function, I want to init a char array and add it to the char pointer ptr. I call the function like that:
char* ptr= NULL;
ValArgument(ptr);
The pointer returned still has the value NULL. Why? I expected that the pointer will point onto the char array str[].
The pointer returned still has the value NULL. Why?
Because you passed the pointer by value. That means that the function is given a separate copy of the pointer, and any changes it makes to the pointer will not affect the caller's copy.
You can either pass by reference:
void ValArgument(char *& ptr)
// ^
or return a value:
char * ValArgument();
I expected that the pointer will point onto the char array str[].
No; once you've fixed that problem, it will point to the undead husk of the local variable that was destroyed when the function returned. Any attempt to use the pointer will cause undefined behaviour.
Depending on what you need to do with the string, you might want:
a pointer to a string literal, char const * str = "hello world";. Note that this should be const, since string literals can't be modified.
a pointer to a static array, static char str[] = "hello world";. This means that there is only one string shared by everyone, so any modification will affect everyone.
a pointer to a dynamically allocated array. Don't go there.
a string object, std::string str = "hello world";. This is the least error-prone, since it can be passed around like a simple value.
Related
I have a function that is returning a string. However, when I call it and do c_str() on it to convert it into a const char*, it only works when I store it into another string first. If I directly call c_str() off of the function, it stores garbage value in the const char*.
Why is this happening? Feel like I'm missing something very fundamental here...
string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value
static string SomeFunction()
{
string str;
// does some string stuff
return str;
}
SomeFunction().c_str() gives you a pointer to a temporary(the automatic variable str in the body of SomeFunction). Unlike with references, the lifetime of temporaries isn't extended in this case and you end up with charArray being a dangling pointer explaining the garbage value you see later on when you try to use charArray.
On the other hand, when you do
string str_copy = SomeFunction();
str_copy is a copy of the return value of SomeFunction(). Calling c_str() on it now gives you a pointer to valid data.
The value object returned by a function is a temporary. The results of c_str() are valid only through the lifetime of the temporary. The lifetime of the temporary in most cases is to the end of the full expression, which is often the semicolon.
const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.
The workaround is to make sure that you use the result of c_str() before the end of the full expression.
#include <cstring>
char *strdup(const char *src_str) noexcept {
char *new_str = new char[std::strlen(src_str) + 1];
std::strcpy(new_str, src_str);
return new_str;
}
const char *p = strdup(SomeFunction.c_str());
Note that strdup is a POSIX function, so if you are a platform that supports POSIX, it's already there.
The "string str" in method SomeFunction() is a local variable in SomeFunction(), and only survives inside the scope of SomeFunction();
Since the return type of the method SomeFunction() is string, not a reference of string, after "return str;", SomeFunction() will return a copy of the value of str, which will be stored as a temporary value in some place of memory, after the call of SomeFunction(), the temporary value will be destroyed immediately;
"string str = SomeFunction();" will store the returned temporary value of SomeFunction() to string str, actually is a copy of that value and stored to str, a new memory block is allocated, and the lifetime of str is bigger than the returned temporary value of SomeFunction(), after the ";" the call of SomeFunction() is finished, and the returned temporary value is destroyed immediately, the memory is recycled by system, but the copy of this value is still stored in str. That is why "const char* strConverted = str.c_str();" can get the right value, actually c_str() returned a pointer of the initial element of str (the first element memory address of str pointed string value), not the returned temporary value of SomeFunction();
"const char* charArray= SomeFunction().c_str();" is different, "SomeFunction().c_str()" will return a pointer of the initial element of the returned temporary value (the first element memory address of returned temporary string value), but after the call of SomeFunction(), the returned temporary value is destroyed, and that memory address is reused by the system, charArray can get the value of that memory address, but not the value you expected;
Use strcpy to copy the string to a locally defined array and your code will work fine.
I have one function which have argument as char** I need to pass an array value in the same argument how could I pass that?
int fun(char** val)
{
std::cout<<"val:"<<*val<<"\n";
}
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
fun(&ch[0]) // here how can I pass the char array getting build issue
}
I think it is best to figure out, what the intent of the function fun is on the basis of the signature, i.e. the type of the parameter:
fun takes a pointer to a pointer to a single character or to the beginning of a bunch of characters. In the first place this means fun wants to have a "reference" to a pointer. This usually means func wants to modify this pointer and pass this modification back to the caller. It seams val is in fact an out parameter containing a pointer. If this is you actual intend, go with this function signature! In this case you would call fun this way:
char *c = NULL;
fun(&c);
// c is set by fun to a certain value
If you simply want to print out the characters it is way easier and much more obvious for a reader of your code to change the signature of fun to
int fun(char *val) { /* ... */ }
This says fun takes a pointer to a single character or a bunch of characters. It will get this pointer by value, any modification to the pointer itself won't be visibly outside of fun. In this case you'll call fun by
char c[] = "Hello World!";
fun(c);
Now, why did you get a build issue: The type of &ch[0] is char *, i.e. a pointer to some characters. But your fun expected char **, i.e. a pointer to a pointer to some characters. That's clearly an issue. And it contradicts the intend expressed by the function signature too: fun wants to have a "reference" to a pointer in order to modify this referenced pointer.
Edit: So, it sounds like you're stuck with a weird API and need to pass an character array into a function expecting a char ** parameter. In this case the other answers provide the correct, albeit still questionable solution:
char c[] = "Hello World";
char *ptr = &c[0];
fun(&ptr);
The ptr points to the first character of c. The variable ptr has itself an address, namely &ptr, which has type char **. So &ptr is the needed "reference" to a pointer to a bunch of characters you can pass to fun.
But be aware of the fact, that fun is free to change the value of ptr, i.e. the address ptr itself points to. It might be possible that, returning from the call to fun, the value of ptr is something completely different, pointing to an address you didn't expect. Heck, it might be even possible that you're expected to call free(ptr) at the end even though you started with an address in ptr to some static memory you shall never call free() to. To know these details you have to read the detailed specifications of the function fun.
ch is a char[] array. &ch[0] is dereferencing the array to access the 1st element, yielding a char, and then is taking the address of that char, yielding a char*. But the function wants a char** instead. So save that char* to a variable and pass the address of that variable to the function, eg:
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
char *ptr = ch; // same as: ptr = &ch[0]
fun(&ptr);
}
I have a function that is returning a string. However, when I call it and do c_str() on it to convert it into a const char*, it only works when I store it into another string first. If I directly call c_str() off of the function, it stores garbage value in the const char*.
Why is this happening? Feel like I'm missing something very fundamental here...
string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value
static string SomeFunction()
{
string str;
// does some string stuff
return str;
}
SomeFunction().c_str() gives you a pointer to a temporary(the automatic variable str in the body of SomeFunction). Unlike with references, the lifetime of temporaries isn't extended in this case and you end up with charArray being a dangling pointer explaining the garbage value you see later on when you try to use charArray.
On the other hand, when you do
string str_copy = SomeFunction();
str_copy is a copy of the return value of SomeFunction(). Calling c_str() on it now gives you a pointer to valid data.
The value object returned by a function is a temporary. The results of c_str() are valid only through the lifetime of the temporary. The lifetime of the temporary in most cases is to the end of the full expression, which is often the semicolon.
const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.
The workaround is to make sure that you use the result of c_str() before the end of the full expression.
#include <cstring>
char *strdup(const char *src_str) noexcept {
char *new_str = new char[std::strlen(src_str) + 1];
std::strcpy(new_str, src_str);
return new_str;
}
const char *p = strdup(SomeFunction.c_str());
Note that strdup is a POSIX function, so if you are a platform that supports POSIX, it's already there.
The "string str" in method SomeFunction() is a local variable in SomeFunction(), and only survives inside the scope of SomeFunction();
Since the return type of the method SomeFunction() is string, not a reference of string, after "return str;", SomeFunction() will return a copy of the value of str, which will be stored as a temporary value in some place of memory, after the call of SomeFunction(), the temporary value will be destroyed immediately;
"string str = SomeFunction();" will store the returned temporary value of SomeFunction() to string str, actually is a copy of that value and stored to str, a new memory block is allocated, and the lifetime of str is bigger than the returned temporary value of SomeFunction(), after the ";" the call of SomeFunction() is finished, and the returned temporary value is destroyed immediately, the memory is recycled by system, but the copy of this value is still stored in str. That is why "const char* strConverted = str.c_str();" can get the right value, actually c_str() returned a pointer of the initial element of str (the first element memory address of str pointed string value), not the returned temporary value of SomeFunction();
"const char* charArray= SomeFunction().c_str();" is different, "SomeFunction().c_str()" will return a pointer of the initial element of the returned temporary value (the first element memory address of returned temporary string value), but after the call of SomeFunction(), the returned temporary value is destroyed, and that memory address is reused by the system, charArray can get the value of that memory address, but not the value you expected;
Use strcpy to copy the string to a locally defined array and your code will work fine.
I have a function that is returning a string. However, when I call it and do c_str() on it to convert it into a const char*, it only works when I store it into another string first. If I directly call c_str() off of the function, it stores garbage value in the const char*.
Why is this happening? Feel like I'm missing something very fundamental here...
string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value
static string SomeFunction()
{
string str;
// does some string stuff
return str;
}
SomeFunction().c_str() gives you a pointer to a temporary(the automatic variable str in the body of SomeFunction). Unlike with references, the lifetime of temporaries isn't extended in this case and you end up with charArray being a dangling pointer explaining the garbage value you see later on when you try to use charArray.
On the other hand, when you do
string str_copy = SomeFunction();
str_copy is a copy of the return value of SomeFunction(). Calling c_str() on it now gives you a pointer to valid data.
The value object returned by a function is a temporary. The results of c_str() are valid only through the lifetime of the temporary. The lifetime of the temporary in most cases is to the end of the full expression, which is often the semicolon.
const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.
The workaround is to make sure that you use the result of c_str() before the end of the full expression.
#include <cstring>
char *strdup(const char *src_str) noexcept {
char *new_str = new char[std::strlen(src_str) + 1];
std::strcpy(new_str, src_str);
return new_str;
}
const char *p = strdup(SomeFunction.c_str());
Note that strdup is a POSIX function, so if you are a platform that supports POSIX, it's already there.
The "string str" in method SomeFunction() is a local variable in SomeFunction(), and only survives inside the scope of SomeFunction();
Since the return type of the method SomeFunction() is string, not a reference of string, after "return str;", SomeFunction() will return a copy of the value of str, which will be stored as a temporary value in some place of memory, after the call of SomeFunction(), the temporary value will be destroyed immediately;
"string str = SomeFunction();" will store the returned temporary value of SomeFunction() to string str, actually is a copy of that value and stored to str, a new memory block is allocated, and the lifetime of str is bigger than the returned temporary value of SomeFunction(), after the ";" the call of SomeFunction() is finished, and the returned temporary value is destroyed immediately, the memory is recycled by system, but the copy of this value is still stored in str. That is why "const char* strConverted = str.c_str();" can get the right value, actually c_str() returned a pointer of the initial element of str (the first element memory address of str pointed string value), not the returned temporary value of SomeFunction();
"const char* charArray= SomeFunction().c_str();" is different, "SomeFunction().c_str()" will return a pointer of the initial element of the returned temporary value (the first element memory address of returned temporary string value), but after the call of SomeFunction(), the returned temporary value is destroyed, and that memory address is reused by the system, charArray can get the value of that memory address, but not the value you expected;
Use strcpy to copy the string to a locally defined array and your code will work fine.
I have a function that is returning a string. However, when I call it and do c_str() on it to convert it into a const char*, it only works when I store it into another string first. If I directly call c_str() off of the function, it stores garbage value in the const char*.
Why is this happening? Feel like I'm missing something very fundamental here...
string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value
static string SomeFunction()
{
string str;
// does some string stuff
return str;
}
SomeFunction().c_str() gives you a pointer to a temporary(the automatic variable str in the body of SomeFunction). Unlike with references, the lifetime of temporaries isn't extended in this case and you end up with charArray being a dangling pointer explaining the garbage value you see later on when you try to use charArray.
On the other hand, when you do
string str_copy = SomeFunction();
str_copy is a copy of the return value of SomeFunction(). Calling c_str() on it now gives you a pointer to valid data.
The value object returned by a function is a temporary. The results of c_str() are valid only through the lifetime of the temporary. The lifetime of the temporary in most cases is to the end of the full expression, which is often the semicolon.
const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.
The workaround is to make sure that you use the result of c_str() before the end of the full expression.
#include <cstring>
char *strdup(const char *src_str) noexcept {
char *new_str = new char[std::strlen(src_str) + 1];
std::strcpy(new_str, src_str);
return new_str;
}
const char *p = strdup(SomeFunction.c_str());
Note that strdup is a POSIX function, so if you are a platform that supports POSIX, it's already there.
The "string str" in method SomeFunction() is a local variable in SomeFunction(), and only survives inside the scope of SomeFunction();
Since the return type of the method SomeFunction() is string, not a reference of string, after "return str;", SomeFunction() will return a copy of the value of str, which will be stored as a temporary value in some place of memory, after the call of SomeFunction(), the temporary value will be destroyed immediately;
"string str = SomeFunction();" will store the returned temporary value of SomeFunction() to string str, actually is a copy of that value and stored to str, a new memory block is allocated, and the lifetime of str is bigger than the returned temporary value of SomeFunction(), after the ";" the call of SomeFunction() is finished, and the returned temporary value is destroyed immediately, the memory is recycled by system, but the copy of this value is still stored in str. That is why "const char* strConverted = str.c_str();" can get the right value, actually c_str() returned a pointer of the initial element of str (the first element memory address of str pointed string value), not the returned temporary value of SomeFunction();
"const char* charArray= SomeFunction().c_str();" is different, "SomeFunction().c_str()" will return a pointer of the initial element of the returned temporary value (the first element memory address of returned temporary string value), but after the call of SomeFunction(), the returned temporary value is destroyed, and that memory address is reused by the system, charArray can get the value of that memory address, but not the value you expected;
Use strcpy to copy the string to a locally defined array and your code will work fine.