14

I am a newbie to C. I am trying to return a 2d array from a function. It is something like this

int *MakeGridOfCounts(int Grid[][6])
{
  int cGrid[6][6] = {{0, }, {0, }, {0, }, {0, }, {0, }, {0, }};
  int (*p)[6] = cGrid;
  return (int*)p;
}

I know this causes an error, need help. thanks

user1047092
  • 1,481
  • 4
  • 17
  • 18
  • 2
    Please post the errors it causes. Also, problem #1 is that the array you're allocating is on the stack, and will be gone once the function returns. – Dan Fego Dec 23 '11 at 15:48

3 Answers3

21

The C language has a basic flaw: it is impossible to return arrays from functions. There are many workarounds for this; i'll describe three.

Replace by a pointer to an array

Return a pointer instead of an array itself. This leads to another problem in C: when a function returns a pointer to something, it should usually allocate the something dynamically. You should not forget to deallocate this later (when the array is not needed anymore).

typedef int (*pointer_to_array)[6][6];

pointer_to_array workaround1()
{
    pointer_to_array result = malloc(sizeof(*result));
    (*result)[0][0] = 0;
    (*result)[1][0] = 0;
    (*result)[2][0] = 0;
    (*result)[3][0] = 0;
    (*result)[4][0] = 0;
    (*result)[5][0] = 0;
    return result;
}

Replace by a pointer to int

A 2-D array appears just as a sequence of numbers in memory, so you can replace it by a pointer to first element. You clearly stated that you want to return an array, but your example code returns a pointer to int, so maybe you can change the rest of your code accordingly.

int *workaround2()
{
    int temp[6][6] = {{0}}; // initializes a temporary array to zeros
    int *result = malloc(sizeof(int) * 6 * 6); // allocates a one-dimensional array
    memcpy(result, temp, sizeof(int) * 6 * 6); // copies stuff
    return result; // cannot return an array but can return a pointer!
}

Wrap with a structure

It sounds silly, but functions can return structures even though they cannot return arrays! Even if the returned structure contains an array.

struct array_inside
{
    int array[6][6];
};

struct array_inside workaround3()
{
    struct array_inside result = {{{0}}};
    return result;
}
anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • Could you please explain in *Replace by a pointer to an array* example, what is the `sizeof` `result`. – gonidelis Mar 26 '19 at 19:07
  • `result` is a pointer to the array, so `sizeof result` is the size of a pointer (typically 4 or 8 bytes, for any pointer). I don't think any explanation on `sizeof result` is necessary, because my code uses `sizeof(*result)`, which is the size of the array. – anatolyg Jul 10 '19 at 12:08
2

It sounds like you want a function returning pointer to array[6] of int:

int (*makeGrid())[6]
{
     return calloc(6*6,sizeof(int)); //zeros the memory as in your example.
}

You would call and use it like so:

int (*arr)[6] = makeGrid();
arr[4][3] = 3; //etc...
Dave
  • 10,964
  • 3
  • 32
  • 54
-2

Try this out, compiles fine with GCC on my mac..

typedef struct _intGrid_t{
    int **data;
    int width;
    int height;
} *IntGrid;

IntGrid makeGridWithSize(int width, int height);
IntGrid makeGridWithSize(int width, int height)
{
    IntGrid grid = malloc(sizeof(struct _intGrid_t));

    int **data = (int **) malloc(sizeof(int *) * width);

    for (int i = 0; i < width; i++) {
        data[i] = malloc(sizeof(int) * height);

        memset(data[i], 0, sizeof(int) * height);
    }

    grid->data = data;
    grid->width = width;
    grid->height = height;

    return grid;
}

void printGrid(IntGrid grid);
void printGrid(IntGrid grid)
{
    printf(" { \n");
    for (int i =0; i < grid->width; i++) {
        printf(" { ");

        for (int j = 0; j < grid->height; j++) {
            printf("%i", grid->data[i][j]);

            if (j != grid->height - 1)
            {
                printf(", ");
            }
        }

        printf(" } \n");
    }
    printf(" } \n");
}

void freeGrid(IntGrid grid);
void freeGrid(IntGrid grid)
{
    for (int i = 0; i < grid->width; i++) {
        free(grid->data[i]);
    }

    free(grid->data);
    free(grid);
}


int main (int argc, const char * argv[])
{
    srand((int) time(NULL));

    IntGrid grid = makeGridWithSize(10, 10);


    for (int i = 0; i < grid->width; i++) {
        for (int j = 0; j < grid->height; j++) {
            grid->data[i][j] = rand() % 10;
        }
    }

    printGrid(grid);
    freeGrid(grid);

    return 0;
}
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201