Dave
Dave

Reputation: 421

Returning a 2D char array in C

I messed around with this enough but I really don't get it.

Here is what I want to do: Take a 2D char array as an input in a function, change the values in it and then return another 2D char array.

That's it. Quite simple idea, but ideas do not get to work easily in C.

Any idea to get me started in its simplest form is appreciated. Thanks.

Upvotes: 5

Views: 12886

Answers (6)

shimpossible
shimpossible

Reputation: 366

The following will do what you want. it will print "One" and "Ten". Also note that it is typed to the exact array dimensions of 10 and 8.

char my_array[10][8] = 
{
{"One"},
{"Two"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"Nine"},
{"Ten"},
};

void foo ( char (**ret)[10][8] )
{
  *ret = my_array;
}

void main()
{
  char (*ret)[10][8];
  foo(&ret);

  printf("%s\r\n", (*ret)[0] )
  printf("%s\r\n", (*ret)[9] )
}

The original question was about RETURNING the array, so I'm updating this to show returning a value. You can't "return an array" directly, but you CAN make a typedef of an array and return that...

char my_array[10][8];
typedef char ReturnArray[8];
ReturnArray* foo()
{
  return my_array;
}

Upvotes: 0

Steve Greene
Steve Greene

Reputation: 502

Here's another example. Tested and works.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void test(char**,unsigned int,unsigned int);

const unsigned int sz_fld = 50 + 1;
const unsigned int sz_ffld = 10;

int main(void) {
    char fld[sz_ffld][sz_fld];
    for (unsigned char i=0;i<sz_ffld;++i) {
        strcpy(fld[i],"");
    }

    strcpy(fld[0],"one");
    strcpy(fld[1],"two");
    strcpy(fld[2],"three");

    char** pfld = malloc(sz_ffld*sizeof(char*));
    for (unsigned int i=0;i<sz_ffld;++i) {
        *(pfld+i) = &fld[i][0];
    }

    test(pfld,sz_ffld,sz_fld);

    printf("%s\n",fld[0]);
    printf("%s\n",fld[1]);
    printf("%s\n",fld[2]);

    free(pfld);

    return(0);
}

void test(char** fld,unsigned int m,unsigned int n) {
    strcpy(*(fld+0),"eleven");
    strcpy(*(fld+1),"twelve");
    return;
}

Note the following:

For compiling, I am using gcc with the C99 option.

I defined the function to include the two sizes information, but I wrote very basic code and am not actually using the information at all, just the strcpy(), so this certainly is not security-safe code in any way (even though I'm showing the "m" and "n" for such facility). It merely shows a technique for making a static 2D char array, and working with it in a function through the intermediate of an array of pointers to the "strings" of the array.

Upvotes: 1

sarnold
sarnold

Reputation: 104080

C will not return an array from a function.

You can do several things that might be close enough:

  • You can package your array in struct and return that. C will return structs from functions just fine. The downside is this can be a lot of memory copying back and forth:

    struct arr {
        int arr[50][50];
    }
    
    struct arr function(struct arr a) {
        struct arr result;
        /* operate on a.arr[i][j]
           storing into result.arr[i][j] */
        return result;
    }
    
  • You can return a pointer to your array. This pointer must point to memory you allocate with malloc(3) for the array. (Or another memory allocation primitive that doesn't allocate memory from the stack.)

    int **function(int param[][50]) {
        int arr[][50] = malloc(50 * 50 * sizeof int);
        /* store into arr[i][j] */
        return arr;
    }
    
  • You can operate on the array pointer passed into your function and modify the input array in place.

    void function(int param[][50]) {
        /* operate on param[i][j] directly -- destroys input */
    }
    
  • You can use a parameter as an "output variable" and use that to "return" the new array. This is best if you want the caller to allocate memory or if you want to indicate success or failure:

    int output[][50];
    
    int function(int param[][50], int &output[][50]) {
        output = malloc(50 * 50 * sizeof int);
        /* write into output[i][j] */
        return success_or_failure;
    }
    

    Or, for the caller to allocate:

    int output[50][50];
    
    void function(int param[][50], int output[][50]) {
        /* write into output[i][j] */
    }
    

Upvotes: 10

moshbear
moshbear

Reputation: 3322

char **foo(const char * const * bar, size_t const *bar_len, size_t len0) {
    size_t i;        
    char** arr = malloc(sizeof(char *) * len0);
    for (i = 0; i < len0; ++i) {
        arr[i] = malloc(bar_len[i]);
        memcpy(arr[i], bar[i], bar_len[i]);
    }
    /* do something with arr */
    return arr;
}

Somewhere else in your code:

char **pp;
size_t *pl;
size_t ppl;
/* Assume pp, pl are valid */
char **pq = foo(pp, pl, ppl);
/* Do something with pq */
/* ... */
/* Cleanup pq */
{
    size_t i;
    for (i = 0; i < ppl; ++i)
        free(pq[i]);
    free(pq);
} 

Because you're passing by-pointer instead of by-value and you want to write to the input array, you have to make a copy of it.

Upvotes: 1

pmg
pmg

Reputation: 108988

You cannot return an array from a function.

You have several options:

  • wrap arrays inside structs
struct wraparray {
    int array[42][42];
};

struct wraparray foobar(void) {
    struct wraparray ret = {0};
    return ret;
}
  • pass the destination array, as a pointer to its first element (and its size), to the function; and change that array
int foobar(int *dst, size_t rows, size_t cols, const int *src) {
    size_t len = rows * cols;
    while (len--) {
        *dst++ = 42 + *src++;
    }
    return 0; /* ok */
}

// example usage
int x[42][42];
int y[42][42];
foobar(x[0], 42, 42, y[0]);
  • change the original array
int foobar(int *arr, size_t rows, size_t cols) {
    size_t len = rows * cols;
    while (len--) *arr++ = 0;
    return 0; /* ok */
}

Upvotes: 5

aleph_null
aleph_null

Reputation: 5786

When you pass a 2D array to a function as a parameter, you need to explicitly tell it the size of the arrays second dimension

void MyFunction(array2d[][20]) { ... }

Upvotes: 0

Related Questions