使用malloc定义2D数组并对其进行修改

时间:2010-08-27 13:40:26

标签: c

如何使用malloc定义2D数组? (比如10X20)。

第二,我可以在不创建新增加的数组并将所有数据复制到其中的情况下增加行数或列数吗?

例如,如何分配内存,使数组为10x30或15x20?

感谢!

7 个答案:

答案 0 :(得分:10)

10X30:

int(*array)[30] = malloc((sizeof *array) * 10);

15x20:

int(*array)[20] = malloc((sizeof *array) * 15);

调整为20x25:

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 <line:5:3, col:17> 'int' '='
    (ArraySubscriptExpr 0xba62c80 <col:3, col:13> 'int'
      (ImplicitCastExpr 0xba62c60 <col:3, col:10> 'int *' <ArrayToPointerDecay>
        (ArraySubscriptExpr 0xba62c20 <col:3, col:10> 'int [10]'
          (DeclRefExpr 0xba62bdc <col:3> 'int (*)[10]' Var='array' 0xba62a00)
          (IntegerLiteral 0xba62c00 <col:9> 'int' 4)))
      (IntegerLiteral 0xba62c40 <col:12> 'int' 9))
    (IntegerLiteral 0xba62ca0 <col:17> 'int' 0))

  // array1[19][9][4] = 0;
  (BinaryOperator 0xba630b8 <line:8:3, col:22> 'int' '='
    (ArraySubscriptExpr 0xba63078 <col:3, col:18> 'int'
      (ImplicitCastExpr 0xba63058 <col:3, col:15> 'int *' <ArrayToPointerDecay>
        (ArraySubscriptExpr 0xba63018 <col:3, col:15> 'int [5]'
          (ImplicitCastExpr 0xba62ff8 <col:3, col:12> 'int (*)[5]' <ArrayToPointerDecay>
            (ArraySubscriptExpr 0xba62fa0 <col:3, col:12> 'int [10][5]'
              (DeclRefExpr 0xba62f5c <col:3> 'int (*)[10][5]' Var='array1' 0xba62db0)
              (IntegerLiteral 0xba62f80 <col:10> 'int' 19)))
          (IntegerLiteral 0xba62fc0 <col:14> 'int' 9)))
      (IntegerLiteral 0xba63038 <col:17> 'int' 4))
    (IntegerLiteral 0xba63098 <col:22> 'int' 0)))

请注意,每个数组下标表达式都会获取一个指针,添加索引的值,并生成所寻址的元素。如果该子元素是一个数组,它将被衰减为指向其第一个元素的指针。这实际上与为声明的数组

所做的步骤实际上没有什么不同
int main() {
  int array[5][10] = { };
  array[4][9] = 1;
}

产生一个非常相似的AST,只有最内在的表达式首先被衰减为指向其第一个元素的指针

  // array[4][9] = 1;
  (BinaryOperator 0xbf9f7e8 <line:5:3, col:17> 'int' '='
    (ArraySubscriptExpr 0xbf9f7a8 <col:3, col:13> 'int'
      (ImplicitCastExpr 0xbf9f788 <col:3, col:10> 'int *' <ArrayToPointerDecay>
        (ArraySubscriptExpr 0xbf9f748 <col:3, col:10> 'int [10]'
          (ImplicitCastExpr 0xbf9f728 <col:3> 'int (*)[10]' <ArrayToPointerDecay>
            (DeclRefExpr 0xbf9f6cc <col:3> 'int [5][10]' Var='array' 0xbfa81f0))
          (IntegerLiteral 0xbf9f6f0 <col:9> 'int' 4)))
      (IntegerLiteral 0xbf9f768 <col:12> 'int' 9))
    (IntegerLiteral 0xbf9f7c8 <col:17> 'int' 1)))

答案 1 :(得分:5)

虽然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 ];

虽然这不是直接的2D阵列,但它有效,在我看来它是最简单的。但是如果你想使用[][]语法,你必须指向指针,例如:

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];

答案 2 :(得分:3)

// 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,尽管重新生成不同大小的矩阵并复制值可能更容易。

答案 3 :(得分:0)

  

第二,我可以增加行数   或cols而不创建新的   增加数组并复制所有数据   对吗?

不,您无法更改数组的大小。 你可以做的是使用指针和realloc来做到这一点。

答案 4 :(得分:0)

2D阵列是一维阵列的一维阵列。由于数组只是一个指针,因此数组数组是一个指针数组。因此,使用malloc分配一个指针数组(每个指针代表一个collumn),然后再次使用它来分配各个数组(每个数组代表一行)。

要展开/缩小数组,请使用realloc (reference)。这是一个示例代码:

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

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有点生锈:)

答案 5 :(得分:0)

您应该更好地“将矩阵包裹”成一维数组int[row][col],而不是使用int[row*col]

以下是示例代码:

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

#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);
}

如果重新分配是一个问题,可能会出现问题。你应该使用双维版本。

答案 6 :(得分:0)

虽然这是一个老问题,但这是我不同的解决方案。

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

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 ~]$