如何使函数返回动态分配的二维数组?

时间:2019-04-05 11:13:57

标签: c arrays multidimensional-array signature

我试图从一个函数返回一个连续的内存分配数组,但是我一直在接收错误。

编译器返回警告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);
}

它应该返回2D数组,但返回错误,并且正在Ubuntu上使用gcc

2 个答案:

答案 0 :(得分:0)

您的分配功能很好,除了一些细节:

  • 您应将rowscols作为参数传递
  • 您应为size_ti使用类型j,并迭代到rowscols而不是硬编码边界。
  • 您应该在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

答案 1 :(得分:0)

如果全部,您需要的是

  

从函数返回连续的内存分配数组

您可以忽略此答案。

如果您要使用动态分配的连续内存块为二维容器(如矩阵)建模,则可以定义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;
}