【问题标题】:2D array as contiguous block of memory二维数组作为连续的内存块
【发布时间】:2015-10-05 06:01:39
【问题描述】:

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

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 中一样。

【问题讨论】:

标签: c arrays memory malloc


【解决方案1】:

不存在您应该像您一样使用分段 malloc 调用的情况。这是广泛传播但不好且不正确的做法。正如您所指出的,它不会在相邻内存中为您提供真正的 2D 数组,而是一个碎片化的、缓慢的混乱。

如何正确地做到这一点:

在标准 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 版本中,您将不得不编写一个“错位数组”:

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

free(arr);

【讨论】:

  • 为什么你称最后一个重整数组我不知道。别的东西让我很困惑。第一种情况sizeof(*arr)等于4个字节(或计算机的字长),是否等于rows * columns * sizeof(int)
  • @Nik-Lz 之所以称为“mangled”是因为在访问它时不能使用常规的二维数组语法,而是必须计算数组索引。 sizeof(*an_array_pointer) 确实 not 等于 4 个字节,而是数组的大小。这是数组指针和普通指针的区别。
【解决方案2】:

要分配一个连续内存,你必须使用

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

【讨论】:

  • 在 SO 上搜索二维数组的连续内存分配
【解决方案3】:

您需要为每个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. 在 C 中强制转换 malloc 的结果毫无意义。我已将其删除。

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

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

【讨论】:

  • 您的解决方案已经在我的问题中,请参阅注释“geeksforgeeks.org/dynamically-allocate-2d-array-c 点号 4。
  • 你不能按照你想要的方式去做
  • @iharob 好吧....好吧,似乎每个人都这么认为,但你能告诉我为什么不能这样做吗?
  • @Wlad 哇。第四种方法乍一看真的令人困惑。在代码中的 arr[0] = (int*)(malloc(rows*columns*sizeof(int))) 之后尝试 int i; for(i = 0; i &lt; rows; i++) arr[i] = (arr[0] + i * columns);
  • 但是,这不会在相邻的内存单元中分配二维数组。
【解决方案4】:

对于 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 可以带来健康的健康状况。

【讨论】:

  • 但是,这不会在相邻的内存单元中分配二维数组。
  • 数据单元是一个连续的数组。
  • 哦,对了……只看到了指针数组分配并将其关闭。无论如何,这段代码完全晦涩难懂,你为什么要写这样的东西?只需分配一块相邻的内存,不需要指针数组。
  • OP 想要(或至少使用)一个指针数组;我修复了他所说的不起作用(它不起作用,因为 83% 的指针未初始化)所以它确实起作用了。
猜你喜欢
  • 2022-01-06
  • 2012-11-12
  • 1970-01-01
  • 2013-02-05
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
相关资源
最近更新 更多