Возвращает 2d-массив из функции

Я новичок в C. Я пытаюсь вернуть 2d-массив из функции. Это что-то вроде этого

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

Я знаю, что это вызывает ошибку, нужна помощь. спасибо

Ответ 1

Язык C имеет основной недостаток: невозможно вернуть массивы из функций. Для этого существует много обходных решений; я опишу три.

Заменить указателем на массив

Возвращает указатель вместо самого массива. Это приводит к другой проблеме в C: когда функция возвращает указатель на что-то, она обычно должна выделять что-то динамически. Вы не должны забывать освободить это позже (когда массив больше не нужен).

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;
}

Заменить указателем на int

2-мерный массив появляется как последовательность чисел в памяти, поэтому вы можете заменить его указателем на первый элемент. Вы четко заявили, что хотите вернуть массив, но ваш примерный код возвращает указатель на int, поэтому, возможно, вы можете соответствующим образом изменить остальную часть вашего кода.

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!
}

Обертка со структурой

Звучит глупо, но функции могут возвращать структуры, даже если они не могут возвращать массивы! Даже если возвращаемая структура содержит массив.

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

struct array_inside workaround3()
{
    struct array_inside result = {{{0}}};
    return result;
}

Ответ 2

Похоже, вы хотите, чтобы функция возвращала указатель на массив [6] из int:

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

Вы вызывали бы и использовали бы его так:

int (*arr)[6] = makeGrid();
arr[4][3] = 3; //etc...

Ответ 3

Попробуйте это, компилируется с GCC на моем 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;
}