49

I've tried the following:

char[10] testfunc()
{
    char[10] str;

    return str;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Datoxalas
  • 1,261
  • 5
  • 14
  • 23
  • 2
    So, you have tried *one thing*, it didn't work, and now you ask? Have you used the search function? Have you looked at the suggestions made when you asked the question? Have you looked at the *Related* list on the right side of this page? Questions like this have been asked a bajillion times here on SO, so with *minimal* effort, you should have been able to find a solution. – Björn Pollex Apr 14 '11 at 08:35
  • 1
    This question has been asked (and answered) many times. Take a look at: [how to return an array in a c method](http://stackoverflow.com/questions/4264304/howto-return-a-array-in-a-c-method) – razlebe Apr 14 '11 at 08:36
  • See also: [C FAQ Chapter 19: Returning arrays](http://c-faq.com/~scs/cclass/int/sx5.html). – DarkDust Apr 14 '11 at 08:46
  • 3
    Reopened because the [alleged duplicate](https://stackoverflow.com/questions/3473438/c-return-array-in-a-function) was not, and the answer to that not applicable here. – Cheers and hth. - Alf Jan 12 '18 at 03:14

7 Answers7

71

Best as an out parameter:

void testfunc(char* outStr){
  char str[10];
  for(int i=0; i < 10; ++i){
    outStr[i] = str[i];
  }
}

Called with

int main(){
  char myStr[10];
  testfunc(myStr);
  // myStr is now filled
}
Xeo
  • 129,499
  • 52
  • 291
  • 397
31

You have to realize that char[10] is similar to a char* (see comment by @DarkDust). You are in fact returning a pointer. Now the pointer points to a variable (str) which is destroyed as soon as you exit the function, so the pointer points to... nothing!

Usually in C, you explicitly allocate memory in this case, which won't be destroyed when the function ends:

char* testfunc()
{
    char* str = malloc(10 * sizeof(char));
    return str;
}

Be aware though! The memory pointed at by str is now never destroyed. If you don't take care of this, you get something that is known as a 'memory leak'. Be sure to free() the memory after you are done with it:

foo = testfunc();
// Do something with your foo
free(foo); 
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marijn van Vliet
  • 5,239
  • 2
  • 33
  • 45
  • 7
    A char array is not the same as a char pointer. See the [C FAQ question 6.2](http://c-faq.com/aryptr/aryptr2.html). – DarkDust Apr 14 '11 at 08:45
  • 2
    to be fair Marjin said 'similar'. From the linked FAQ "Arrays are not pointers, though they are closely related (see question 6.3) and can be used similarly." which is basically what Marjin said. – mostlyWright Dec 20 '20 at 12:51
14

A char array is returned by char*, but the function you wrote does not work because you are returning an automatic variable that disappears when the function exits.

Use something like this:

char *testfunc() {
    char* arr = malloc(100);
    strcpy(arr,"xxxx");
    return arr;
}

This is of course if you are returning an array in the C sense, not an std:: or boost:: or something else.

As noted in the comment section: remember to free the memory from the caller.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
  • 1
    Sorry Felice, but you haven't understood my point; the memory leak is not in the assignment (and strcpy does not help at all, either). It's that you are reserving memory via malloc, but *no one is deallocating that memory* (calling free() in this case). You should note that, in this case, the caller function should check if the poiner is not null, and then free() it after it's used. Otherwise, you are introducing a memory leak. Anyway, it's a bad practice and should be avoided like hell. – Alberto Sep 15 '17 at 08:11
  • @mydaemon well I can't write all the code of the entire program, it is clear that the OP has to free the memory after its usage. As you pointed off, the code before the edit was wrong, because it will cause the loss of the allocated pointer. – Felice Pollano Sep 15 '17 at 09:05
  • I do agree with the change, but as an advice, never assume the op will know the same things than you. It takes literally 30 seconds to add a note: you should be calling free from the caller function". – Alberto Sep 15 '17 at 09:44
  • As stated [here](https://stackoverflow.com/a/5099675/771469), you need to cast the return of `malloc()`. – SteeveDroz Sep 23 '21 at 08:19
9

As you're using C++ you could use std::string.

Flinsch
  • 4,296
  • 1
  • 20
  • 29
  • 3
    As you are answering the question, you could stay on topic. User asked **how** does one return an _char array_ from a function, not **what** should s/he use. The _reasoning_ why exactly char array is unknown. It could be a practice, it could be a homework, it could be looking under the hood... best not to assume. – Danilo Apr 24 '21 at 21:44
4

With Boost:

boost::array<char, 10> testfunc()
{
    boost::array<char, 10> str;

    return str;
}

A normal char[10] (or any other array) can't be returned from a function.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    This does a copy on exit, rather than pass a reference. May not be a problem but for large arrays this could be a substantial cost. However with use of the return value optimisation (http://en.wikipedia.org/wiki/Return_value_optimization) you could completely elide the copy. – tenpn Apr 14 '11 at 08:41
  • 1
    Instead of `boost::array`, one can also use `std::array` and avoid the dependency on boost. – Kai Petzke Apr 26 '21 at 17:44
1

When you create local variables inside a function that are created on the stack, they most likely get overwritten in memory when exiting the function.

So code like this in most C++ implementations will not work:

char[] populateChar()
{
    char* ch = "wonet return me";
    return ch;
}

A fix is to create the variable that want to be populated outside the function or where you want to use it, and then pass it as a parameter and manipulate the function, example:

void populateChar(char* ch){
    strcpy(ch, "fill me, Will. This will stay", size); // This will work as long as it won't overflow it.
}

int main(){
    char ch[100]; // Reserve memory on the stack outside the function
    populateChar(ch); // Populate the array
}

A C++11 solution using std::move(ch) to cast lvalues to rvalues:

void populateChar(char* && fillme){
    fillme = new char[20];
    strcpy(fillme, "this worked for me");
}

int main(){
    char* ch;
    populateChar(std::move(ch));
    return 0;
}

Or this option in C++11:

char* populateChar(){
    char* ch = "test char";
    // Will change from lvalue to r value
    return std::move(ch);
}

int main(){
    char* ch = populateChar();
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
devcodexyz
  • 65
  • 7
0

With c++17 you can use next code:

auto testfunc() {
    union {
        char str[14];
    } res = { .str = "Hello, World!" };
    return res;
}

and then use you string as

const auto str = testfunc();
std::cout << str.str;
magrif
  • 396
  • 4
  • 20