Как сделать функцию, возвращающую динамически размещенный двумерный массив? - PullRequest
2 голосов
/ 05 апреля 2019

Я пытаюсь вернуть непрерывный выделенный массив памяти из функции, но продолжаю получать ошибки.

Компилятор возвращает предупреждение о том, что return from incompatible pointer type [-Wincompatible-pointer-types]

Может кто-нибудь сказать мне, что я делаю неправильно?

int *test() {
    size_t rows, cols;
    // assign rows and cols
    rows = 3;
    cols = 3;
    int count = 0;

    int (*arr)[cols] = malloc(sizeof *arr * rows);
    if (arr) {
        // do stuff with arr[i][j]
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; j++) {
                arr[i][j] = count;
                count++;
            }
            /* code */
        }
    }
    return arr;
}

int main() {    
    size_t rows, cols;
    // assign rows and cols
    rows = 3;
    cols = 3;
    int count = 0;

    int (*arr)[cols] = malloc(sizeof *arr * rows);
    arr = test();

    int i = 0;
    int j = 0;

    for (i = 0; i < rows; ++i) {
        for (j = 0; j < 3; ++j)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    free(arr);
}

он должен вернуть двумерный массив, но возвращает ошибку иЯ использую gcc на Ubuntu

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

Если все , вам нужно

, чтобы вернуть непрерывный выделенный массив памяти из функции

Вы можете проигнорировать этот ответ.

Если вы пытаетесь смоделировать двумерный контейнер (например, матрицу), используя динамически распределенный непрерывный блок памяти, вы можете определить struct и передать его:

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

typedef struct {
    int rows, cols;
    int values[];      // I'm using a Flexible Array Member here.
} iMat;

iMat *alloc_matrix(int rows, int columns)
{
    assert(rows > 0  &&  columns > 0);
    iMat *tmp = malloc(sizeof *tmp + sizeof *(tmp->values) * rows * columns);   
    if (tmp)
    {
        tmp->rows = rows;
        tmp->cols = columns;
    }
    return tmp;
}

void fill_matrix_iota(iMat *m, int start)
{
    if ( m )
        for (size_t i = 0, n = m->rows * m->cols; i < n; ++i)
            m->values[i] = start + i;
}

void print_matrix(iMat *m, int width)
{
    if (m)
    {
        for (int i = 0, k = 0; i < m->rows; ++i)
        {
            for(int j = 0; j < m->cols; ++j, ++k)
            {
                printf("%*.d", width, m->values[k]);
            }
            putchar('\n');
        }
    }
}

iMat *make_transposed(iMat *m)
{
    if ( !m )
        return NULL;
    iMat *tmp = alloc_matrix(m->cols, m->rows);
    if ( tmp )
    {
        for (int i = 0; i < m->rows; ++i)
        {
            for(int j = 0; j < m->cols; ++j)
            {
                tmp->values[j * m->rows + i] = m->values[i * m->cols + j];
            }
        }        
    }
    return tmp;
}

int main(void)
{    
    iMat *a = alloc_matrix(3, 4);
    if (!a)
        exit(EXIT_FAILURE);

    fill_matrix_iota(a, 1);
    print_matrix(a, 3);

    iMat *b = make_transposed(a);
    if (!b)
    {
        free(a);
        exit(EXIT_FAILURE);
    }
    putchar('\n');
    print_matrix(b, 3);

    free(b);
    free(a);

    return EXIT_SUCCESS;
}
0 голосов
/ 05 апреля 2019

Ваша функция распределения в порядке, за исключением нескольких деталей:

  • вы должны передать rows и cols в качестве аргументов
  • вы должны использовать тип size_t дляi и j и итерации к rows и cols вместо жестко закодированных границ.
  • для удобства чтения следует использовать скобки в malloc(sizeof *arr * rows);: malloc (sizeof (* arr) * строки);
  • вы должны вернуть &arr[0][0] или arr[0] для корректности типа.

Проблема в том, что вы не можете определить тип возвращаемого значения test, который будет указателем на2D массив параметрического второго измерения .Следовательно, ошибка типа в присваивании arr = test(); не может быть исправлена.Вы можете обойти этот недостаток, приведя возвращаемое значение к (int (*)[cols]) или просто (void *).

Вот модифицированная версия:

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

int *test(size_t rows, size_t cols) {
    int (*arr)[cols] = malloc(sizeof(*arr) * rows);
    if (arr) {
        // initialize the matrix
        size_t count = 0;
        for (size_t i = 0; i < rows; i++) {
            for (size_t j = 0; j < cols; j++) {
                arr[i][j] = count;
                count++;
            }
            /* code */
        }
        return &arr[0][0];
    }
    return NULL;
}

int main() {
    // assign rows and cols
    size_t rows = 3;
    size_t cols = 3;

    int (*arr)[cols] = (int (*)[cols])test(rows, cols);

    if (arr) {
        for (size_t i = 0; i < rows; i++) {
            for (size_t j = 0; j < cols; j++)
                printf("%d ", arr[i][j]);
            printf("\n");
        }
        free(arr);
    }
    return 0;
}

Вывод:

0 1 2
3 4 5
6 7 8
...