使用malloc定义2D数组并对其进行修改
如何使用malloc定义2D数组? (比如10X20)。
第二,我可以增加行数或列数而不创建新增加的数组并将所有数据复制到它吗?
例如,我如何分配内存,以便arrays为10×30或15×20?
谢谢!
10X30:
int(*array)[30] = malloc((sizeof *array) * 10);
15×20:
int(*array)[20] = malloc((sizeof *array) * 15);
调整为20×25:
int(*array2)[25] = realloc(array, (sizeof *array2) * 20);
外部维度(10,15,20)可以在运行时确定,因为它不需要作为编译器的索引计算的一部分。 内部维度(30,20,25)需要在编译时知道。 希望能帮助到你。
请注意,与指针数组解决方案不同,这个解决方案可以作为单个内存块处理,因为它将所有内容分配到单个内存块中,就像真正声明的数组一样:
memcpy(somewhere, array2, sizeof(int) * 20 * 25); // (sizeof *array2) * 20
但最终还是取决于你的用例。
由于有些人很难理解索引操作对array
所采取的操作,所以让我们在下面的代码中为索引表达式提供了什么
int main() { int(*array)[10] = malloc((sizeof *array) * 5); array[4][9] = 0; int(*array1)[10][5] = malloc((sizeof *array1) * 20); array1[19][9][4] = 0; }
它是一个很好的编译器,可以以易读的方式打印它的AST
// array[4][9] = 0; (BinaryOperator 0xba62cc0 'int' '=' (ArraySubscriptExpr 0xba62c80 'int' (ImplicitCastExpr 0xba62c60 'int *' (ArraySubscriptExpr 0xba62c20 'int [10]' (DeclRefExpr 0xba62bdc 'int (*)[10]' Var='array' 0xba62a00) (IntegerLiteral 0xba62c00 'int' 4))) (IntegerLiteral 0xba62c40 'int' 9)) (IntegerLiteral 0xba62ca0 'int' 0)) // array1[19][9][4] = 0; (BinaryOperator 0xba630b8 'int' '=' (ArraySubscriptExpr 0xba63078 'int' (ImplicitCastExpr 0xba63058 'int *' (ArraySubscriptExpr 0xba63018 'int [5]' (ImplicitCastExpr 0xba62ff8 'int (*)[5]' (ArraySubscriptExpr 0xba62fa0 'int [10][5]' (DeclRefExpr 0xba62f5c 'int (*)[10][5]' Var='array1' 0xba62db0) (IntegerLiteral 0xba62f80 'int' 19))) (IntegerLiteral 0xba62fc0 'int' 9))) (IntegerLiteral 0xba63038 'int' 4)) (IntegerLiteral 0xba63098 'int' 0)))
请注意,每个数组下标表达式都使用指针,添加索引的值,并生成被寻址的元素。 如果该子元素是一个数组,它将被衰减为指向其第一个元素的指针。 这实际上与为声明的数组所做的步骤实际上没有什么不同
int main() { int array[5][10] = { }; array[4][9] = 1; }
产生一个非常相似的AST,只有最内部的表达式首先被衰减为指向其第一个元素的指针
// array[4][9] = 1; (BinaryOperator 0xbf9f7e8 'int' '=' (ArraySubscriptExpr 0xbf9f7a8 'int' (ImplicitCastExpr 0xbf9f788 'int *' (ArraySubscriptExpr 0xbf9f748 'int [10]' (ImplicitCastExpr 0xbf9f728 'int (*)[10]' (DeclRefExpr 0xbf9f6cc 'int [5][10]' Var='array' 0xbfa81f0)) (IntegerLiteral 0xbf9f6f0 'int' 4))) (IntegerLiteral 0xbf9f768 'int' 9)) (IntegerLiteral 0xbf9f7c8 'int' 1)))
虽然malloc()
不直接支持多维数组,但有一些解决方法,例如:
int rows = 10; int cols = 30; int *array = malloc(rows * cols * sizeof(int)); // Element (5,6) int x = 5; int y = 6; int element = array [ x * cols + y ];
虽然这不是直接的2Darrays,但它有效,在我看来它是最简单的。 但是如果你想使用[][]
语法,你必须指向指针,例如:
int rows = 10; int cols = 30; // Rows int **array = malloc(rows * sizeof(int*)); // Cols int i; for(i = 0; i < rows; i++) array[i] = malloc(cols * sizeof(int)); // Element (5,6) int x = 5; int y = 6; int element = array[x][y];
// first allocate the 20 rows, that contain pointers to int // (if the matrix contains int type values) int **a = malloc(20 * sizeof(int *)); // now loop for each row and allocate data for the actual values int i; for(i = 0; i < 20; i++) { a[i] = malloc(10 * sizeof(int)); }
为了增加矩阵的大小,您可以使用realloc
尽管重新生成不同大小的矩阵并复制值可能更容易。
第二,我可以增加行数或列数而不创建新增加的数组并将所有数据复制到它吗?
不,您无法更改数组的大小。 你可以做的是使用指针和realloc来做到这一点。
2Darrays是一维arrays的一维arrays。 由于数组只是一个指针,因此数组数组是一个指针数组。 因此,您使用malloc
分配指针数组(每个指针代表一个collumn),然后再次使用它来分配各个数组(每个数组代表一行)。
要扩展/收缩数组,请使用realloc
(引用) 。 这是一个示例代码:
#include #include int** alloc_matrix(int w, int h) { int** matrix; matrix = (int**) malloc(sizeof(int*) * h); for(int i = 0; i < h; i++) { matrix[i] = (int*) malloc(sizeof(int) * w); } return matrix; } void realloc_matrix(int*** matrix, int new_w, int new_h) { *matrix = (int**) realloc((void *)*matrix, sizeof(int*) * new_h); for(int i = 0; i < new_h; i++) { (*matrix)[i] = (int*) realloc((void *)(*matrix)[i], sizeof(int) * new_w); } } int main(int argc, char* argv[]) { // Allocating matrix int** m = alloc_matrix(10, 15); // Filling with some data for(int y = 0; y < 15; y++) { for(int x = 0; x < 10; x++) { m[y][x] = y * x; // Notice the index is [y][x] - NOT [x][y]! } } // Printing for(int y = 0; y < 15; y++) { for(int x = 0; x < 10; x++) { printf("%d\t", m[y][x]); // Notice the index is [y][x] - NOT [x][y]! } printf("\n"); } // Reallocating realloc_matrix(&m, 20, 10); // Filling with some data for(int y = 0; y < 10; y++) { for(int x = 0; x < 20; x++) { m[y][x] = y * x; // Notice the index is [y][x] - NOT [x][y]! } } // Printing for(int y = 0; y < 10; y++) { for(int x = 0; x < 20; x++) { printf("%d\t", m[y][x]); // Notice the index is [y][x] - NOT [x][y]! } printf("\n"); } }
如果我有什么不对劲,我很抱歉。 我的C-fu有点生锈:)
而不是使用int[row][col]
你应该更好地“将你的矩阵包裹”成一维数组int[row*col]
。
这是示例代码:
#include #include #define DET_MALLOC_FAIL -1 #define DET_READ_FAIL -2 #define DET_WRITE_FAIL -3 typedef struct det_matrix_s { double * vect; size_t order; } det_matrix; void *det_sf_malloc(size_t dsize); det_matrix * det_matrix_new(size_t order); #define DET_MAT_ELEM(matr, i, j) \ ((matr)->vect[((matr)->order * (i)) + (j)]) int det_matrix_read(det_matrix * matr, FILE * src); int det_matrix_write(det_matrix * matr, FILE * dest); void det_matrix_delete(det_matrix * matr); /** * Malloc wrapper */ void * det_sf_malloc(size_t dsize) { void *data = malloc(dsize); if(NULL == data){ exit(DET_MALLOC_FAIL); } return (data); } /** * Allocates memory for a new matrix */ det_matrix * det_matrix_new(size_t order) { det_matrix * res = det_sf_malloc(1 * sizeof(*res)); double * vect = det_sf_malloc(order * order * sizeof(*vect)); res->order = order; res->vect = vect; return (res); } /** * Reads matrix */ int det_matrix_read(det_matrix * matr, FILE * src) { size_t i, j; if(NULL == matr || NULL == src){ return (DET_READ_FAIL); } for(i = 0; i < matr->order; ++i){ for(j = 0; j < matr->order; ++j){ if(stdin == src){ fprintf(stdout, "mat[%d][%d] = ", i, j); } fscanf(src, "%lf", &DET_MAT_ELEM(matr, i, j)); } } return (EXIT_SUCCESS); } /** * Writes matrix **/ int det_matrix_write(det_matrix * matr, FILE * dest) { size_t i, j; if(NULL == matr || NULL == dest){ return (DET_WRITE_FAIL); } for(i = 0; i < matr->order; ++i){ for(j = 0; j < matr->order; ++j){ fprintf(dest, "%5.2lf ", DET_MAT_ELEM(matr, i, j)); } fprintf(dest, "\n"); } return (EXIT_SUCCESS); } /** * Free memory for matrix */ void det_matrix_delete(det_matrix * matr) { free(matr->vect); free(matr); } /** * Main */ int main(int argc, char * argv[]) { det_matrix * mat = det_matrix_new(3); det_matrix_read(mat, stdin); det_matrix_write(mat, stdout); det_matrix_delete(mat); return (EXIT_SUCCESS); }
如果重新分配是一个问题,可能会出现问题。 你应该使用双维版本。
虽然这是一个老问题,但这是我的不同解决方案。
#include #include #include int main(int arvc, char* argv[]) { int (*a)[5][8]; int i, j; a = (int (*)[5][8])calloc(5*8, sizeof(int)); for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) (*a)[i][j] = i *10 + j; } for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) printf("%d ", (*a)[i][j]); printf("\n"); } return 0; }
编译并运行
[user@buzz ~]$ gcc main.c -o main [user@buzz ~]$ [user@buzz ~]$ ./main 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27 30 31 32 33 34 35 36 37 40 41 42 43 44 45 46 47 [user@buzz ~]$