从C中的函数返回多维数组

从c中的函数返回多维数组的最佳方法是什么?

假设我们需要在函数中生成一个多维数组并在main中调用它,最好将它包装在一个结构中,还是只返回一个指向堆内存的指针?

int *create_array(int rows, int columns){ int array[rows][columns] = {0}; return array; } int main(){ int row = 10; int columns = 2; create_array(row,columns); } 

上面的代码,只是为了勾勒出我想到的基本程序。

这是错的:

 int *create_array(int rows, int columns){ int array[rows][columns] = {0}; return array; } 

并应该产生这样的警告:

 prog.c:2:6: note: (near initialization for 'array') prog.c:3:13: warning: return from incompatible pointer type [-Wincompatible-pointer-types] return array; ^~~~~ prog.c:3:13: warning: function returns address of local variable [-Wreturn-local-addr] 

因为你要返回一个自动变量的地址 ; 它的生命周期在其相应的函数终止时结束。


您应该在main()声明一个双指针,通过该函数传递它,为它动态分配内存并返回该指针。 或者你可以在main()创建数组并将双指针传递给函数。


我想知道在堆上分配多维数组并传递它们的方法

要在堆上分配内存,您可以使用这两种方法之一,其中涉及指针

 #include  #include  // We return the pointer int **get(int N, int M) /* Allocate the array */ { /* Check if allocation succeeded. (check for NULL pointer) */ int i, **array; array = malloc(N*sizeof(int *)); for(i = 0 ; i < N ; i++) array[i] = malloc( M*sizeof(int) ); return array; } // We don't return the pointer void getNoReturn(int*** array, int N, int M) { /* Check if allocation succeeded. (check for NULL pointer) */ int i; *array = malloc(N*sizeof(int *)); for(i = 0 ; i < N ; i++) (*array)[i] = malloc( M*sizeof(int) ); } void fill(int** p, int N, int M) { int i, j; for(i = 0 ; i < N ; i++) for(j = 0 ; j < M ; j++) p[i][j] = j; } void print(int** p, int N, int M) { int i, j; for(i = 0 ; i < N ; i++) for(j = 0 ; j < M ; j++) printf("array[%d][%d] = %d\n", i, j, p[i][j]); } void freeArray(int** p, int N) { int i; for(i = 0 ; i < N ; i++) free(p[i]); free(p); } int main(void) { int **p; //getNoReturn(&p, 2, 5); p = get(2, 5); fill(p ,2, 5); print(p, 2, 5); freeArray(p ,2); return 0; } 

选择最适合您的风格。

从c中的函数返回多维数组的最佳方法是什么?

我的建议是避免这样做,并避免使用C中的多维数组(它们不可读且麻烦)。

我建议你的矩阵类型是适当的抽象数据类型 ,由一些以灵活数组成员结尾的struct表示:

 struct mymatrix_st { unsigned nbrows, nbcolumns; int values[]; }; 

这是创建函数(返回一个正确初始化的指向动态内存的指针):

 struct mymatrix_st* create_matrix(unsigned mnbrows, unsigned mnbcolumns) { if (mnbrows > UINT_MAX/4 || mnbcolumns > UINT_MAX/4 ||(unsigned long)mnbrows * (unsigned long)mnbcolums > UINT_MAX) { fprintf(stderr, "too big matrix\n"); exit(EXIT_FAILURE); }; size_t sz = sizeof(struct mymatrix_st)+(mnbrows*mnbcolumns*sizeof(int)); struct mymatrix_st*m = malloc(sz); if (!m) { perror("malloc mymatrix"); exit(EXIT_FAILURE); }; m->nbrows = mnbrows; m->nbcolumns = mnbcolumns; for (unsigned long ix=(unsigned long)mnbrows * (unsigned long)mnbcolumns-1; ix>=0; ix--) m->values[ix] = 0; return m;; } /*end create_matrix*/ 

struct mymatrix_st目的是不包含任何内部指针。 你可以而且应该使用free来销毁它。

这是访问者function; 使它成为一个static inline函数,并在声明struct mymatrix_ststruct mymatrix_st的相同头文件中定义它,例如

 static inline int getmatrix(struct mymatrix_st*m, unsigned row, unsigned col) { if (!m) { fprintf(stderr, "getmatrix with no matrix\n"); exit(EXIT_FAILURE); }; if (row >= m->nbrows || col >= m->nbcolumns){ fprintf(stderr, "getmatrix out of bounds\n"); exit(EXIT_FAILURE); }; return m->values[row*m->nbcolumns + col]; } 

我留给你定义和实现你的抽象struct mymatrix_st类型的其他操作。

(你可以调整代码,也许删除越界检查,但我不建议不安全的代码)

 int** create_array(int rows, int columns){ int** array = malloc(rows * sizeof(int*)); int i; for (i=0; i 

应该做的伎俩。 如果使用int array[rows][columns]; 一旦函数返回它就会死掉,你得到一个UB。 您至少应该使用动态内存分配。

您不能返回一个数组,但是您可以返回一个常规指针和文档,被调用者可以将其视为指向已传递给调用者的维度的多维数组的指针。

(注意,返回的指针必须指向动态或静态,但不是自动内存 – 不返回指向局部变量的指针!)

它需要一些稍微罗嗦的演员表,可能还有一个宏,但它是可行的:

 #include  #include  #include  void* multi(int R, int C) { return calloc ( 1, sizeof(int[R][C]) ); //or sizeof(int)*R*C } int main() { int (*r_)[3][4] = multi(3,4); if(!r_) return EXIT_FAILURE; #define r (*r_) //emulate C++ a reference -- r now behaves as an `int r[3][4];` //Test that addresses advance as they would in a multi-d array int local[3][4]; assert(&local[1][0]-&local[0][0] == 4); //base example assert(&r[1][0]-&r[0][0] == 4); //"returned" multi-d array free(r); //or free(&r) or free(r_) -- here it shouldn't matter #undef r return 0; } 

请注意,指针数组与multi-d数组不同。 一个真正的multi-d数组是一个连续的块,而一个指针数组(虽然可以使用相同的索引语法)具有更糟糕的引用局部性,因此如果你想要更好的性能,这可能比返回指针指针更可取。