【问题标题】:C - allocating a matrix in a functionC - 在函数中分配矩阵
【发布时间】:2013-04-06 22:43:35
【问题描述】:

我正在尝试使用一个获取其维度和三重指针的函数来分配一个矩阵。我已经分配了一个 int**(设置为 NULL)并且我将它的地址作为函数的参数传递。由于某种原因,这给了我一个内存访问冲突。

void allocateMatrix(int ***matrix, int row, int col)
{
    int i;
    if((*matrix = (int**)malloc(row * sizeof(int*))) == NULL)
    {
        perror("There has been an error");
        exit(EXIT_FAILURE);
    }
    for(i = 0; i < row; ++i)
    {
        if((*matrix[i] = (int*)malloc(col * sizeof(int))) == NULL)
        {
            perror("There has been an error");
            exit(EXIT_FAILURE);
        }
    }
}

/* main.c */

    int** matrix = NULL;
    allocateMatrix(&matrix, MATRIX_ROW, MATRIX_COL); //error

【问题讨论】:

  • 你的结构效率低下。使用单个数组而不是数组数组,并使用[y*width+x] 访问
  • @Dave 我知道,但是指针算法已经够吓人了……
  • @Venom 只有一个指针而不是指向指针数组的指针不是更可怕吗? :)
  • @hyde 也许我稍后会更改它,尺寸足够小以防止显示效率低下。我知道 malloc 及其衍生物非常昂贵。

标签: c function matrix malloc


【解决方案1】:

你需要改变

if((*matrix[i] = (int*)malloc(col * sizeof(int))) == NULL)

if(((*matrix)[i] = (int*)malloc(col * sizeof(int))) == NULL)
//  ^       ^

在使用数组下标之前,您需要取消引用matrix
*matrix[i] 等价于*(matrix[i])

【讨论】:

  • 我现在不知道该接受哪一个。你是第一个回答但没有解释的人。无论如何,这对你来说可能是微不足道的:)
  • @Venom 很高兴它为您修复。您可以对多个答案进行投票,也可以接受,因此如果多个答案对您有所帮助,您可以识别多个答案:-)
【解决方案2】:

这是运算符优先级的问题。在

if ((*matrix[i] = (int*)malloc( ... ))

默认优先级是*(matrix[i]),而您应该使用(*matrix)[i]

我仍然建议将矩阵分配为连续数组,而不是作为指向数组的指针数组。

【讨论】:

    【解决方案3】:

    我已经为 gcc C11/C99 做了一个解决方案,基于链接具有适当的分配功能:

    http://c-faq.com/aryptr/dynmuldimary.html

    http://c-faq.com/aryptr/ary2dfunc3.html

    在cmets中经过一番讨论,很明显matrix2被正确分配了,可以将它作为matrix2[0](数据在一维数组),强制转换为 (double (*)[])

    //compile with gcc --std=c11 program.c
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MX 9
    #define MY 14
    
    void input_matrix(int row, int column, double matrix[row][column]);
    void print_matrix(int row, int column, double matrix[row][column]);
    double **alloc_matrix2(int row, int column);
    double  *alloc_matrix3(int row, int column);
    void    *alloc_matrix4(int row, int column);
    
    int main()
    {
        int i=MX, j=MY;
        printf("Generate input values and print matrices with functions fn(int w, int k, double matrix[w][k]) (in C99 and C11)\n");
        double matrix1[i][j];
        input_matrix(MX,MY,matrix1);
        printf("matrix static\n");
        print_matrix(MX,MY,matrix1);
    
    
        double **matrix2; //data of matrix2 is just matrix3                 
        matrix2=alloc_matrix2(MX,MY); 
        input_matrix(MX,MY,(double (*)[])(*matrix2));
        printf("matrix two times allocated one for pointers, the second for data (double (*)[])(m[0])\n");
        print_matrix(MX,MY,(double (*)[])(matrix2[0]));
        free(*matrix2);
        free(matrix2);
    
    
        double *matrix3=alloc_matrix3(MX,MY);
        input_matrix(MX,MY,(double (*)[])matrix3);
        printf("matrix allocated as two-dimensional array\n");
        print_matrix(MX,MY,(double (*)[])matrix3);
        free(matrix3);
    
        j=MY;
        double (*matrix4)[j];
        matrix4 = (double (*)[])alloc_matrix4(MX,MY);
        input_matrix(MX,MY,matrix4);
        printf("matrix allocated via pointer to array m = (double (*)[])malloc(MX * sizeof(*m))\n");
        print_matrix(MX,MY,matrix4);
        free(matrix4);
        printf("\nThe End!\n");
        return 0;
    }
    
    void input_matrix(int row, int column, double matrix[row][column]){
        for(int i=0; i<row; i++){
            for(int j=0; j<column; j++)
                matrix[i][j]=i+1;
        }
    }
    
    void print_matrix(int row, int column, double matrix[row][column]){
        for(int i=0; i<row; i++){
            for(int j=0; j<column; j++)
                printf("%.2lf ", matrix[i][j]);
            printf("\n");
        }
    }
    
    double **alloc_matrix2(int row, int column){
        double **matrix;
        matrix=malloc(row*sizeof(double*));
        matrix[0] = (double *)malloc(row*column*sizeof(double));
        for(int i = 1; i < row; i++)
            matrix[i] = matrix[0]+i*column;
        return matrix;
    }
    
    double *alloc_matrix3(int row, int column){
        double *matrix;
        matrix=malloc(row*column*sizeof(double));
        return matrix;
    }
    
    void *alloc_matrix4(int row, int column){
        double (*matrix)[column];
        matrix = (double (*)[])malloc(row*sizeof(*matrix));
        return matrix;
    }
    

    【讨论】:

    • matrix2 版本会导致未定义的行为(T **T (*)[n] 不同)。将编译器错误隐藏在强制转换后面并不能解决任何问题。
    • matrix3 和 marix4,代码没问题(它有可以删除的不必要的强制转换)但是 cmets 是错误的。 matrix4 是通过指向数组的指针(不是指向数组的指针数组)分配的。
    • @Matt McNabb:我添加了一些新的 cmets。你能解释一下为什么 matrix4 只是通过指向数组的指针而不是 MX 维度的数组吗?而 matrix2 解决方案正在发挥作用:它与 matrix3 相同,但有一个额外的指针数组。 matrix2 的数据是一维数组。
    • Matrix2 不起作用,您有一个正确分配的锯齿状数组,但它不能传递给期望连续内存块的函数。 input_matrix 函数将在第一行末尾的未分配内存上涂鸦(并且 print_matrix 函数读取相同的内存)。在 matrix4 中,您分配一个数组,其每个元素都是另一个数组。返回的是指向外部数组第一个元素的指针。
    • @Matt McNabb:所以这个站点解决方案c-faq.com/aryptr/dynmuldimary.html 是正确的。他们使用了这样的指针数组设计c-faq.com/aryptr/array2.gif。但是 print_matrix 可以读取未分配的内存吗?如何在代码中证明?
    猜你喜欢
    • 2011-01-08
    • 1970-01-01
    • 2015-10-13
    • 2023-03-03
    • 2015-11-10
    • 2013-05-21
    • 2014-07-06
    相关资源
    最近更新 更多