Reputation: 347
I have a local character array in a function that is manipulated according to the logic in the function. The function return the pointer to the array as follows
char * fn(void)
{
char str[20] = "Hello";
cout << str; // This prints the string Hello perfectly
// Some operations on string
return str;
}
int main()
{
char *ptr;
ptr=fn();
cout << ptr; // This prints only the first character of the string i.e H
}
How can I pass an array from a function back to main.
I know I should not pass address of a local variable back to main as that stack of the program is modified. But still if I use cout << *ptr then the output is just the first character "H". I solved the problem by using a dynamically allocated memory for the array using "new". But I would like to know the reason behind this behavious (Does this have to do something with Stack ?? )
Upvotes: 0
Views: 124
Reputation: 7146
If you don't want to use std::string oder std::array, just basic C, change the function fn:
void fn(char *target, size_t target_size)
{
if(target_size < 6)//I used 6 here because thats the size of the string you want write into the array
return; //If the targets size is to small, the function is cancled
strycpy(target, "Hello");
cout << target;
}
int main()
{
char str[20];
fn(str, 20);
std::cout << str;
}
But it generall its better to use std::string as shown above, because this method is unsafe ( Your program will crash if you make target_size bigger then the real size of the array, beause strcpy will write over the arrays limit). Some compilers won't even allow to use this, because of "strcpy".
Another (uncommon) possibility would be to make the array static:
char * fn(void)
{
static char str[20] = "Hello";
cout << str;
return str;
}
Upvotes: 0
Reputation: 27538
Using std::string
will solve all your problems. It's particularly strange that you use C++ streams but C-style strings. Why?
Here's what your code would look like:
#include <string>
#include <iostream>
std::string fn()
{
std::string str = "Hello";
std::cout << str; // This prints the string Hello perfectly
// Some operations on string
return str;
}
int main()
{
std::string str = fn();
std::cout << str;
}
This makes your code cleaner, more robust, exception-safe, easier to read and write and possibly faster. Why in the world wouldn't you do it? (To be fair, there are situations where std::string
isn't appropriate, but first, beginners rarely encounter them, and second, such situations typically also outrule C++ streams.)
As for your original solution...
I know I should not pass address of a local variable back to main as that stack of the program is modified.
Great :) But then why do you do it anyway?
But still if I use cout << *ptr then the output is just the first character "H"
Besides the undefined behaviour resulting from returning a pointer to something that doesn't exist anymore, this sort of thing would happen even with a valid char*
. After all, dereferencing a char*
is not different from dereferencing an int*
or a double*
. It simply yields a char
, and printing a char
prints, well, a character.
int *i = new int(123);
std::cout << *i; // prints 123
double *d = new double(0.5);
std::cout << *d; // prints 0.5
char *c = new char('x');
std::cout << *c; // prints x
The fact that there may be more characters stored in memory right after that one dereferenced char
is irrelevant. You deliver a char
to std::cout
, nothing more. If you deliver a char*
, everything is different, because std::cout
then knows that it must "look for more characters".
Again, using std::string
, you don't need to care for these things.
I solved the problem by using a dynamically allocated memory for the array using "new".
Not a good solution, because then you have the issue of who deletes the string. Without a delete[]
somewhere at the right location in your code, the memory occupied by the string will never be released until your program terminates, which can lead to memory leaks and your end users wondering why YourProgram.exe suddenly takes 800 MB in the Windows Task Manager :)
Again, use std::string
. It frees the allocated memory automatically when it's no longer needed.
Upvotes: 1
Reputation: 6132
Yes by returning str, you are returning an address of the stack memory that no longer exists. The correct way of doing it is to allocate memory, pass it to fn, and then free it so that the same function is allocating and deallocating memory.
Upvotes: 2
Reputation: 249462
Yes, it has to do with the "stack." Specifically the "lifetime" of the function-local variable is only until the function ends. And returning the pointer copies only the pointer and not what it points to, so you end up with a dangling pointer and undefined behavior.
This is C++ after all, so the easiest thing to do here is simply make your function return std::string
. That way it's a "value" rather than a pointer and returning it will make a copy (n.b. an optimizing compiler can elide the copy, but the functionality will remain the same).
Upvotes: 2
Reputation: 541
if you create the array in the function how you did it, it is in deed created on the stack, and will be destroyed, when you leave the function. A usual way to manipulate arrays through functions would be, to pass the pointer to an already existing array as a function parameter. When you modify it in the function then, it will also be modified outside of the function.
Upvotes: 2