51

Im fairly new to coding in C and currently im trying to create a function that returns a c string/char array and assigning to a variable.

So far, ive observed that returning a char * is the most common solution. So i tried:

char* createStr() {
    char char1= 'm';
    char char2= 'y';
    char str[3];
    str[0] = char1;
    str[1] = char2;
    str[2] = '\0';
    char* cp = str;
    return cp;
}

My question is how do I use this returned char* and assign the char array it points to, to a char[] variable?

Ive tried (all led to noob-drowning errors):

  1. char* charP = createStr();
  2. char myStr[3] = &createStr();
  3. char* charP = *createStr();
Xantium
  • 11,201
  • 10
  • 62
  • 89
user1993177
  • 573
  • 2
  • 6
  • 9

5 Answers5

70

Notice you're not dynamically allocating the variable, which pretty much means the data inside str, in your function, will be lost by the end of the function.

You should have:

char * createStr() {

    char char1= 'm';
    char char2= 'y';

    char *str = malloc(3);
    str[0] = char1;
    str[1] = char2;
    str[2] = '\0';

    return str;

}

Then, when you call the function, the type of the variable that will receive the data must match that of the function return. So, you should have:

char *returned_str = createStr();

It worths mentioning that the returned value must be freed to prevent memory leaks.

char *returned_str = createStr();

//doSomething
...

free(returned_str);
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Rubens
  • 14,478
  • 11
  • 63
  • 92
  • 4
    `sizeof(char)` is guaranteed to be 1 & there is no reason to typecast the `malloc` return – Aniket Inge Jan 22 '15 at 04:37
  • 1
    @Aniket +1 Thanks for the comment. I've been told that sometimes by friends, but I guess I didn't understand the issue by the time, and later on hadn't thought of that again :D – Rubens Jan 22 '15 at 09:00
12

If you want to return a char* from a function, make sure you malloc() it. Stack initialized character arrays make no sense in returning, as accessing them after returning from that function is undefined behavior.

change it to

char* createStr() {
    char char1= 'm';
    char char2= 'y';
    char *str = malloc(3 * sizeof(char));
    if(str == NULL) return NULL;
    str[0] = char1;
    str[1] = char2;
    str[2] = '\0';
    return str;
}
Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • 10
    It worths mentioning that the returned value must be freed to prevent memory leaks. `char* astr = createStr(); doSomething(astr); free(astr);` – Vassilis Mar 15 '16 at 17:47
  • This was what I was looking for! I was a bit confused thinking since returning a pointer from the function may cause memory leaks. Your answer solved my question. So then memory held by char *astr is finally released. (In Java, for eg. I understand this is not a problem, because the garbage collector would take care) – hrushi Feb 23 '17 at 19:46
7

you can use a static array in your method, to avoid lose of your array when your function ends :

char * createStr() 
{
    char char1= 'm';
    char char2= 'y';

    static char str[3];  
    str[0] = char1;
    str[1] = char2;
    str[2] = '\0';

    return str;
}

Edit : As Toby Speight mentioned this approach is not thread safe, and also recalling the function leads to data overwrite that is unwanted in some applications. So you have to save the data in a buffer as soon as you return back from the function. (However because it is not thread safe method, concurrent calls could still make problem in some cases, and to prevent this you have to use lock. capture it when entering the function and release it after copy is done, i prefer not to use this approach because its messy and error prone.)

Linosa
  • 31
  • 7
A.R.S.D.
  • 180
  • 3
  • 13
  • 3
    It's probably worth mentioning some of the disadvantages (all calls share the same storage, so calls will overwrite previous results, and nothing is thread-safe). – Toby Speight Feb 26 '20 at 18:09
6
char* charP = createStr();

Would be correct if your function was correct. Unfortunately you are returning a pointer to a local variable in the function which means that it is a pointer to undefined data as soon as the function returns. You need to use heap allocation like malloc for the string in your function in order for the pointer you return to have any meaning. Then you need to remember to free it later.

Paul
  • 139,544
  • 27
  • 275
  • 264
3

Including "string.h" makes things easier. An easier way to tackle your problem is:

#include <string.h>
    char* createStr(){
    static char str[20] = "my";
    return str;
}
int main(){
    char a[20];
    strcpy(a,createStr()); //this will copy the returned value of createStr() into a[]
    printf("%s",a);
    return 0;
}
Adnan
  • 166
  • 10
  • 1
    Why make a copy? `char *a = createStr();` would work the same. – melpomene Mar 11 '17 at 11:56
  • Yes you can use that too and that'll save some memory, it's just that he asked for a way to "assign the char array it (function) points to, to a char[] variable" so I told him just that. – Adnan Mar 12 '17 at 13:15