Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the Right Way to Write a C Function Returning a char array?

i'm quite familiar with Java, not so in C.

In Java, if i have a method that does something and returns a String, it would look like:

private String doSomething(...) {
    String s;
    // do something;
    return s;
}

The syntactic equivalent in C would not work and is plain wrong:

char* doSomething(...) {
    char s[100];
    // do something;
    return s;
}

of course i can do:

char* doSomething(...) {
    char *s;
    s = malloc(100 * sizeof(char));
    // do something;
    return s;
}

which would work (i think!) but i seldom see codes doing this way (is it because it's unnecessarily filling the heap?)

most commonly, i see:

bool doSomething(char *s) {
    // do something that copies chars to s
    return true;
}

And the calling statements would be:

char s[100];
doSomething(s);

What if I do not know the size of the char array until inside the function itself? i.e. I would not be able to declare the char array outside the function and then pass it in.

What would be the correct way to deal with such a scenario?

like image 262
Edwin Lee Avatar asked Nov 29 '11 13:11

Edwin Lee


People also ask

Can a function return a char array in C?

C programming does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.


Video Answer


2 Answers

Let the calling code be responsible for allocating the memory. Pass in the buffer and the length of the buffer in example 2:

bool doSomething(char *s, size_t buflen)
{ 
    // do something that copies chars to s up to max of buflen
    return true; 
} 

This tends to reduce leaks, since the calling code is in control of the memory management.

like image 107
Mitch Wheat Avatar answered Oct 08 '22 17:10

Mitch Wheat


An example of static allocation case (you are obliged to think about the maximum buffer size at compile time)

buf[MAX_NO];
do(buf, MAX_NO);

_Bool do(char *s, size_t len) { 
// use len as boundary in your operations
}

or dynamic allocation case (using malloc as you said and using pointers to save the buffer location and size)

char *s = NULL;
size_t final_len;
do(&s, &final_len);

_Bool do(char** s, size_t* final_len) {
    size_t len = discoverSize();
    char* buf = (char*) malloc(sizeof(char) * len);

    *s = buf; //save memory location
    *final_len = len; //save buffer size
    // use len as boundary in your operations

}

// do whatever
free(s); //remember to free the buffer for politeness
like image 26
ziu Avatar answered Oct 08 '22 16:10

ziu