二维数组作为连续的内存块

2D array as contiguous block of memory

我知道这个问题已得到解答,但不知何故对我不起作用。 我像这样为数组动态分配内存:

arr = (int**)(malloc(rows*sizeof(int*)));
arr[0] = (int*)(malloc(rows*columns*sizeof(int))); // <-- THIS DOESN'T WORK

printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {   
    //arr[row] = (int*)(malloc(columns*sizeof(int))); <---THIS WORKS
    arr[row][col] = num;
    printf("%d ", arr[row][col]);
    if((++col == columns)){
        row++;          
        col = 0;
        printf("\n");
    }
}

如果矩阵是 6x6,它会在第 4 行后抛出分段错误。 有什么建议吗?谢谢

编辑: 请参阅:http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ 第 4 点。如果我按照第 3 点那样做,它就会起作用。但我需要它,就像 4 中那样。

您需要为每个 row 分配内存,而不仅仅是第一个 row。替换

arr[0] = (int*)(malloc(rows*columns*sizeof(int)));

for(int i = 0; i < rows; i++)
    arr[i] = malloc(columns * sizeof(int));

此处所做的更改是:

  1. 所有行都将分配 columns * sizeof(int) 字节的内存。
  2. 转换 malloc 的结果在 C 中毫无意义。我已将其删除。

您可能需要在循环中添加检查以防止溢出。像

if(row == rows)
{
    puts("Matrix full; Exiting loop...");
    break;
}

固定代码为

int i, row = 0, col = 0;
int rows = 6, columns = 6; /* For 6x6 matrix */

arr = malloc(rows * sizeof(int*));
for(i = 0; i < rows; i++)
    arr[i] = malloc(columns * sizeof(int));

printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {   
    arr[row][col] = num;
    printf("%d ", arr[row][col]);
    if(++col == columns){
        row++;          
        col = 0;
        printf("\n");
    }
    if(row == rows)
    {
        puts("Matrix full; Exiting loop...");
        break;
    }
}

要分配连续内存,您必须使用

arr  = malloc(sizeof(int *) * rows);
arrayData = malloc(sizeof(int) * columns * rows);

for(i = 0; i < rows; i++)
     arr[i]  = arrayData + i * columns ;

要解除分配,您需要

free( arrData );
free( arr );

here

对于 6x6 矩阵,动态内存是多余的。你应该简单地使用:

int arr[rows][cols];

这更简单、更清晰、更快速、更不容易出错,而且总体上更安全——只要您将矩阵大小保持得足够小,以便轻松放入堆栈即可。如果您需要一个大矩阵(比如 1 MiB 以上,但您需要调整阈值以适应您的系统),那么动态内存是相关的。

您可以对 arr[0] 进行单一分配,但您必须对 arr[1]arr[5] 中的每一个进行显式分配。我是这样做的:

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

int main(void)
{
    int rows = 6;
    int cols = 6;
    int **arr = (int**)(malloc(rows*sizeof(int*)));
    arr[0] = (int*)(malloc(rows*cols*sizeof(int)));

    for (int i = 1; i < rows; i++)
        arr[i] = arr[i-1] + cols;

    printf("\nArray: \n");
    for (int i = 0; i < rows; i++)
    {   
        for (int j = 0; j < cols; j++)
            arr[i][j] = (i+1) * (cols + 1 - j);
    }

    for (int i = 0; i < rows; i++)
    {   
        for (int j = 0; j < cols; j++)
            printf("%3d", arr[i][j]);
        putchar('\n');
    }

    free(arr[0]);
    free(arr);
    return(0);
}

示例输出:

Array: 
  7  6  5  4  3  2
 14 12 10  8  6  4
 21 18 15 12  9  6
 28 24 20 16 12  8
 35 30 25 20 15 10
 42 36 30 24 18 12

运行valgrind健康状况良好

在任何情况下您都应该像现在这样使用碎片化的 malloc 调用。这是一种广泛传播但不好且不正确的做法。正如您所指出的,它不会在相邻内存中为您提供真正的二维数组,而是零散的、缓慢的混乱。

如何正确执行此操作:

在标准C中,写

int (*arr)[rows][columns] = malloc (sizeof(*arr));
(*arr)[r][c] = something;
...

free(arr);

或者如果您更喜欢使用更易于阅读(但可能更难理解)的语法:

int (*arr)[columns] = malloc (sizeof(int[rows][columns]));
arr[r][c] = something;
...

free(arr);

在过时的 C 版本中,您必须编写 "mangled array":

int* arr = malloc(rows * columns * sizeof(*arr));
arr[r*c] = something;
...

free(arr);