首页 > 解决方案 > 使用指针将二维数组传递给函数

问题描述

谁能解释 print() 函数有什么问题?

printf("Control") 从不工作,输出是分段错误 11

int main(int argc, char **argv){
int m=5,n=4;    // matrix[5][4]
int a=50,b=20;  // range: 20-50

int **matrix;

imatrix(matrix,m,n,a,b);
print(matrix,m,n);

第一步:用值填充地址

    void imatrix(int **matrix,int m,int n,int max, int min){
    srand(time(NULL));
    int i=0,j=0;
    
    matrix = (int **)malloc( m * sizeof(int*) );
    if( matrix == NULL ){
        printf( "memory req.!" );
    }
    
    
    for( i = 0; i < m; i++ ) {
        matrix[i] = (int *)malloc( n * sizeof(int) );
        if( matrix[i] == NULL ){
            printf( "memory req.!" );
        }
    }
    
    
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            matrix[i][j]=(rand()%(max-min))+min;
            printf("%2d ",matrix[i][j]);
        }
        printf("\n\n");
    }
    }

到这里为止一切都很好。我得到分段错误:下面的代码和“控制”行之后的 11 永远不起作用

void print(int **matrix, int m, int n){
int i,j;
for(i=0; i < m; i++){
    for(j=0; j < n; j++){
       printf("%d",*(*(matrix + i) + j));
    }
    printf("\n");
}

printf("control");
}

标签: csegmentation-faultdynamic-memory-allocation

解决方案


这不是printf("control")which segfaults (尽管你最好不要使用printf它:考虑将其更改为puts("control"),这也会输出换行符。)这是之前打印矩阵的尝试,它正在取消引用未初始化的值。

发生这种情况是因为您的imatrix函数没有返回它创建的矩阵,并且matrix您的 inmain没有任何值。

事实上,imatrix不返回任何东西,因为它被定义为返回void。它需要一个matrix参数,我想它是一个输出参数,但是:

  • 该参数的类型错误,无法作为输出参数(输出参数必须是指向要返回的对象的指针;)

  • 它从不尝试使用指向要返回的对象的指针来返回对象。

为了符合这些要求,您需要原型

void imatrix(int*** matrix, int m, int n, int max, int min);

并且您必须为matrix[注 1] 的每次使用添加一个额外的间接级别:

    *matrix = malloc(m * sizeof(**matrix));
    if (*matrix == NULL) {
        printf( "memory req.!" );
        /* NOTE: You shouldn't attempt to continue after the malloc fails.
         * Return immediately and let the caller deal with the malloc failure.
         */
    }

    for( i = 0; i < m; i++ ) {
        (*matrix)[i] = malloc( n * sizeof(*(*matrix)[i])) );
        if( (*matrix)[i] == NULL ){
    // etc.

我认为我们可以同意这是一个主要的 PITA,除非必要,否则不值得麻烦。

就个人而言,我发现除非绝对必要,否则根本不使用输出参数不会让人感到困惑。在这种情况下,根本没有必要,因为您可以只返回指针来分配内存:

/* CHANGE: Prototype */
int** imatrix(int m, int n, int max, int min){
    srand(time(NULL)); /* TODO: This initialisation should really be done in main */
    int i=0, j=0;
    
    /* CHANGE: matrix is a local variable */
    int** matrix = malloc( m * sizeof(*matrix) );
    /* CHANGE: Immediate return on malloc failure */
    if( matrix == NULL ) {
        return matrix;
    }
    
    for( i = 0; i < m; i++ ) {
        matrix[i] = malloc( n * sizeof(*matrix[i]) );
        if( matrix[i] == NULL ){
            printf( "memory req.!" );
        }
    }
    
    
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            matrix[i][j]=(rand()%(max-min))+min;
            printf("%2d ",matrix[i][j]);
        }
        printf("\n\n");
    }

    /* CHANGE: matrix is returned */
    return matrix;
}

这有一个稍微不同的使用模式:

int main(int argc, char **argv){
    int m=5, n=4;    // matrix[5][4]
    int a=50, b=20;  // range: 20-50

    /* CHANGE: imatrix returns the new matrix */
    int **matrix = imatrix(m, n, a, b);
    /* CHANGE: check for failure */
    if (matrix == NULL) {
         fprintf(stderr, "%s\n", "imatrix failed to allocate memory.");
         exit(1);
    }

    print(matrix, m, n);
    /* TODO: Free the storage allocated for matrix */
}

笔记

  1. 在这段代码中,我改变了 malloc 的用法:

    lvalue = (RedundantCast*)malloc(count * sizeof(FixedType));
    

    到惯用 C:

    lvalue = malloc(count * sizeof(*lvalue));
    

    的返回值的显式转换malloc在 C 中充其量是没有意义的,因为malloc返回 avoid*并且 C 很乐意自动将 avoid*转换为任何类型的指针。使用目标 ( ) 指向的对象的类型sizeof(*lvalue)而不是插入特定类型可以保护您免受类型在未来编辑中更改的可能性,并且您忘记在所有调用中进行更改malloc。(例如,考虑如果您决定制作matrix一个矩阵long long而不是会发生什么int。)


推荐阅读