如何使用尺寸未知的2D数组?

我正在为矩阵乘法编写C函数。 它需要两个二维2D数组。 如果我知道输入数组的大小,我可以这样做,但我想做一个更通用的function。

如何在编译时不知道产品的尺寸时如何找到它们的尺寸以及如何返回数组?

如果只有指向数组开头的指针,则无法找到数组的维数。 您需要将数组的维度传递给函数。

这个答案完全矫枉过正,但这是我基于struct的方法,其中nm称为“整个’其他故事。”

如果这是一个新程序(即你要定义你的函数的输入/输出是什么样的)并且你打算用矩阵做很多工作,我会倾向于用一个结构来表示一个矩阵,而且只是传递指向该结构实例的指针。

下面的代码显示了一种可能的方法。 请注意,这里有一些“技巧”。 首先,数据全部存储在一个连续的块中 – 由于多种原因,这可能会提高性能。 这种技术的一个潜在缺点是调整矩阵的大小变得昂贵,因为你必须分配一个全新的实例并复制数据。 但是如果你发现这是一个问题,你总是可以改变你的实现,假设你总是使用matrix_get()和matrix_set()函数来访问矩阵中的值。

此外,矩阵结构和数据指针指向的内存全部在单个malloc调用中分配。 如果您使用此技术,请注意数据对齐问题。 例如,如果将数据更改为指向64位整数或双精度数,则需要添加填充以确保所有内容都是8字节对齐的。 或者,只需将数据指针malloc作为new_matrix()函数中的单独数组,前提是您记得在free_matrix()释放它。

我作为练习留给OP来编写乘法函数。

 #include  #include  struct matrix { int rows; int cols; int * data; }; struct matrix * new_matrix( int rows, int cols ) { struct matrix * m = NULL; /* Allocate a block of memory large enough to hold the matrix 'header' struct * as well as all the row/column data */ m = malloc( sizeof(struct matrix) + (rows * cols * sizeof(int) ) ); if( m ) { m->rows = rows; m->cols = cols; /* Some ugly pointer math to get to the first byte of data */ m->data = (int*) ( (char *) m + sizeof(*m) ); } return m; } void free_matrix( struct matrix * m ) { free( m ); } int matrix_set( struct matrix * m, int row, int col, int val) { if( col >= m->cols || row >= m->rows ) return -1; m->data[ m->cols * row + col ] = val; return 0; } int matrix_get( struct matrix * m, int row, int col, int * val) { if( col >= m->cols || row >= m->rows ) return -1; else { *val = m->data[ m->cols * row + col ]; return 0; } } void print_matrix( struct matrix * m ) { int r,c; int val; for( r = 0; r < m->rows; r++ ) { for( c = 0; c < m->cols; c++ ) { matrix_get( m, r, c, &val ); printf( "%5d%s", val, c + 1 < m->cols ? "," : "" ); } printf("\n"); } } int main (int argc, char **argv) { int r,c; struct matrix * m = new_matrix( 5, 5 ); for( r = 0; r < m->rows; r++ ) { for( c = 0; c < m->cols; c++ ) { matrix_set( m, r, c, (r +1)* 10 + c + 1 ); } } print_matrix( m ); free_matrix( m ); return 0; } 

C中没有真正的2D数组。只有数组的数组,这些数组并不完全相同。 (我知道我会因为这样说而受到殴打。请耐心等待。)

虽然差异可能看起来不是很显着,但确实如此。 要使用数组,您不必在编译时知道它的维度。 例如

 double dot_product (double a[], double b[], int size); /* an A-OK function */ 

但是,您必须知道任何数组元素的大小。 例如

 void matrix_product (double a[][], double b[][], double result[][], int a_rows, int a_cols, int b_cols); /* Bad, would not compile. You are only permitted to say "double[N][]", where N is known at compile time */ 

如果你想要完全通用的矩阵操作代码,你需要使用普通的1D数组,并自己计算行数和列数的索引。 你还必须传递尺寸。

 void matrix_product (double a[], double b[], double result[], int a_rows, int a_cols, int b_cols) { ... for (col = 0; col < a_cols; ++col) { for (row = 0; row < a_rows; ++row) { ... ... a[row*a_cols + col] ... ... 

在此示例中,调用者分配result ,而不是乘法函数。


在某些更高级别,您将希望将矩阵与其维度封装在某种forms的抽象矩阵数据类型中,如下所示:

 struct matrix { double* elements; int rows, cols; }; 

但这是一个完整的'其他故事。

您最好为arrays创建MATRIX结构。 正如@David指出的那样,在C中,你必须自己跟踪尺寸。 语言中没有内置function可以安全地为您完成此操作。

字符串有strlen()等函数(即:以\ 0结尾的char数组),但不包括数组之类的函数。 跟踪这一点的最简单方法是创建自己的抽象数据类型和辅助函数。

试试这个:

 typedef struct matrix { int **array; int rows; int cols; } matrix_t; int createMatrix(matrix_t* mtx) { int i; if (!mtx) { printf("INVALID POINTER TO MATRIX"); return -1; } if ( (mtx->rows == 0) || (mtx->cols == 0) ) { printf("Rows/columns cannot be zero!"); return -1; } int status = 0; // allocate the array mtx->array = (int **)calloc(mtx->rows,sizeof(int*)); if(mtx->array != NULL) { // memory allocation succeeded for(i = 0; i < mtx->rows; i++) { if((mtx->array[i] = (int*)calloc(mtx->cols,sizeof(int))) == NULL) { printf("Memory allocation error"); status = -1; break; } else { // Allocation successful } } } else { printf("Memory allocation error!"); status = -1; } return status; } int destroyMatrix(matrix_t* mtx) { // destroy the array for(i = 0; i < mtx->rows; i++) { if(mtx->array[i] != NULL) { free(mtx->array[i]); mtx->array[i] = NULL; } } if(mtx->array) { free(mtx->array); mtx->array = NULL; } return 0; } 

现在您可以创建一个新的矩阵结构,设置其行/列值,调用createMatrix,然后设置:

  matrix_t myMtx; myMtx.array = NULL; myMtx.rows = 3; myMtx.cols = myMtx.cols; // Make it a square matrix if(createMatrix(&myMtx) == 0 ) { printf("Created matrix successfully"); } else { printf("Failed to create matrix!"); } 

这些函数还可以检查内存分配是否失败,并通过在使用之前检查所有指针来避免程序崩溃(即:SEGFAULT)。

祝好运!

您需要传递数组的尺寸。 然后,您必须动态分配第三个数组来保存结果。 计算结果矩阵后,可以返回指向它的指针。

尝试沿着这些线的东西,其中A是nxm矩阵,B是mxp矩阵:

 int* matix_multiply(int* matrix_a, int* matrix_b, int n, m, int p){ int *result = (int *) malloc(sizeof(int) * a_rows * b_cols); if(result == NULL) exit(EXIT_FAILURE); //loops to do the actual multiplication and store the results in result[i][j] return result; //returns the result array } 
 #include  void foo(int *a, int m, int n) { for(int i=0; i 

通常,2Darrays以行主要方式存储。 2D数组可以被视为指向一组元素的指针数组。 由于我们也传递了两个维度,因此我们可以相应地访问元素。

即使您可以尝试其他数据类型。 下面我使用了结构。

 #include  struct abc { int a; float b; char c; }; void foo(struct abc *a, int m, int n) { for(int i=0; ia, (a+i*n+j)->b, (a+i*n+j)->c); } int main() { struct abc a[][2] = {{{1,1.0,'a'},{2,2.0,'b'}}, {{3,3.0,'c'},{4,4.0,'d'}}}; foo((struct abc *)a,2,2); return 0; } 

希望能帮助到你....!!!!!