【问题标题】:Adding 2 matrices using pointers使用指针添加 2 个矩阵
【发布时间】:2018-03-12 18:20:36
【问题描述】:

我可以通过将(c,a,b) 传递给add_mat 函数来实现它,其中a,b 的结果存储在c 中,

void add_mat(int c[][3], int a[][3], int b[][3], int m, int n)

如果我想这样构造函数,add_mat的返回类型应该是什么

?? add_mat(int a[][3], int b[][3], int m, int n)

下面是示例代码

#include<stdio.h>

void read_mat(int a[][3], int m, int n){
    //scan data
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            printf("[%d][%d] : ",i,j);
            a[i][j]=i+j;
        }
    }   
}
int* add_mat(int a[][3], int b[][3], int m, int n){
    int c[3][3];
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            c[i][j]=a[i][j]+b[i][j];
        }
    }
    return c;
}

int main(){
    int a[3][3];
    int m=2,n=2; //mxn of a matrix

    read_mat(a, m, n);

    //add
    int b[3][3];
    read_mat(b, m, n);
    int* c[3][3];
    c = add_mat(a,b,m,n);

    return 0;
}

就像将add_mat 函数中的计算值c 传递或指向main 函数中的变量一样。

【问题讨论】:

  • 我建议int c[3][3]; add_mat(c, a, b, m, n);

标签: c arrays function pointers multidimensional-array


【解决方案1】:

在您的代码add_mat 中,返回指向仅在函数执行时存在的变量的指针。您可以使用动态分配的矩阵来实现您的目标。

在 C 语言中,通常通过指向矩阵行的指针作为第一个参数传递动态分配的矩阵:

void foo(int** matrix, size_t m, size_t n);

这里的matrix 是指向指针数组的指针。该数组中的每个指针都指向矩阵的行。所以,matrix[0] 指向包含矩阵第一行的数组。

对于任何大小的数组,通常使用size_t 类型。

如果您需要动态创建矩阵,请注意内存。每个动态分配的块都应该被释放。否则你会得到内存泄漏,这可能会导致程序崩溃。因此,当你分配矩阵的行时,你应该检查当前行的分配是否成功。如果没有,您应该释放所有先前分配的行。

您的问题有一个有效的代码:

#include <stdio.h>
#include <stddef.h>
#include <malloc.h>

void free_mat(int** a, size_t m) {
    if (!a) {
        return;
    }

    for (size_t i = 0; i < m; ++i) {
        free(a[i]);
    }

    free(a);
}

int** create_mat(size_t m, size_t n) {
    int** rows = calloc(m, sizeof(int*));
    if (!rows) {
        return NULL;
    }

    for (size_t i = 0; i < m; i++) {
        rows[i] = malloc(n * sizeof(int));
        if (!rows[i]) {
            free_mat(rows, m);
            return NULL;
        }
    }

    return rows;
}

void read_mat(int** a, size_t m, size_t n) {
    for (size_t i = 0; i < m; i++) {
        for (size_t j = 0; j < n; j++) {
            printf("[%d][%d]: ", i, j);
            scanf("%d", a[i] + j);
        }
    }
}

void print_mat(const int* const* a, size_t m, size_t n) {
    for (size_t i = 0; i < m; ++i) {
        for (size_t j = 0; j < n; ++j) {
            printf("[%d][%d]: %d\n", i, j, a[i][j]);
        }
    }
}

int** add_mat(const int* const* a, const int* const* b, size_t m, size_t n) {
    int** c = create_mat(m, n);
    if (c) {
        for (size_t i = 0; i < m; ++i) {
            for (size_t j = 0; j < n; ++j) {
                c[i][j] = a[i][j] + b[i][j];
            }
        }
    }
    return c;
}

int main() {
    size_t m = 3;
    size_t n = 3;

    int** a = create_mat(m, n);
    int** b = create_mat(m, n);

    if (!a || !b) {
        printf("error when allocating matrix\n");
    }
    else {
        read_mat(a, m, n);
        read_mat(b, m, n);

        int** c = add_mat(a, b, m, n);
        if (!c) {
            printf("error when allocating matrix\n");
        }
        else {
            print_mat(c, m, n);
            free_mat(c, m);
        }
    }

    free_mat(a, m);
    free_mat(b, m);

    return 0;
}

但如果add_mat 不创建新矩阵,您会更加灵活。 通常将指向结果矩阵的指针作为函数参数传递:

void add_mat(int** c, const int* const* a, const int* const* b, size_t m, size_t n);

【讨论】:

    【解决方案2】:

    哦,是的,指针...

    在 C 中,本地声明的数组通常分配在堆栈上(而不是堆上),这意味着它们在各自范围之外是无效的。

    换句话说,在你的函数add_mat()中,c在技术上是可以返回的,但是只要函数被执行,它指向的地址只会包含有意义的矩阵数据。

    从函数返回后,函数的返回值是一个指针,该指针仍然包含(指向)在函数执行期间存储矩阵的地址 em>,但是那个位置的内容,即矩阵数据,现在可以包含任意垃圾了。

    所以你所做的在技术上是可行的(即不会引发编译错误),但绝对不是你想要的。

    其次,你的int* c[3][3]; 可能不是你想要的。您在这里声明 cpointer to int 的二维数组(矩阵)。这是不正确的,因为您要处理 int 值,而不是 指针int 值(它们是地址)。

    要解决这两个问题,只需编写 int c[3][3]; 而不是 int* c[3][3]; 并将 add_mat() 函数更改如下:

    void add_mat(int a[][3], int b[][3], int c[][3], int m, int n){
    
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                c[i][j]=a[i][j]+b[i][j];
            }
        }
    }
    

    然后像这样调用那个函数:

    add_mat(a,b,c,m,n);
    

    【讨论】:

    • 这就是我将c,a,b 传递给函数的原因。很好的解释了解引擎盖内发生的事情。@gsamaras 根据我的用例回答。
    • 谢谢。如果我的解释对你有用,那为什么不点赞:-)
    【解决方案3】:

    您不能这样做,因为当函数终止时,c 矩阵的内存将消失。

    您需要使用malloc() 动态分配它,以免内存被释放,除非调用free()。我在2D dynamic array (C) 中有一些例子,如果你想看看。

    使用您之前的函数,您将在函数外部(在main())创建矩阵c,这就是不需要动态内存分配的原因。


    PS:您应该在启用警告的情况下编译:

    prog.c: In function 'add_mat':
    prog.c:19:12: warning: returning 'int (*)[3]' from a function with incompatible return type 'int *' [-Wincompatible-pointer-types]
         return c;
                ^
    prog.c:19:12: warning: function returns address of local variable [-Wreturn-local-addr]
    prog.c: In function 'main':
    prog.c:32:7: error: assignment to expression with array type
         c = add_mat(a,b,m,n);
           ^
    prog.c:31:10: warning: variable 'c' set but not used [-Wunused-but-set-variable]
         int* c[3][3];
              ^
    

    这是一个工作示例,仅用于演示目的:

    #include <stdio.h>
    #include <stdlib.h>
    
    void read_mat(int a[][2], int n, int m){
        //scan data
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                a[i][j] = i + j ;
            }
        }
    }
    
    int **get(int N, int M) /* Allocate the array */
    {
        /* Check if allocation succeeded. (check for NULL pointer) */
        int i, **table;
        table = malloc(N*sizeof(int *));
        for(i = 0 ; i < N ; i++)
            table[i] = malloc( M*sizeof(int) );
        return table;
    }
    
    void print(int** p, int N, int M) {
        int i, j;
        for(i = 0 ; i < N ; i++)
            for(j = 0 ; j < M ; j++)
                printf("array[%d][%d] = %d\n", i, j, p[i][j]);
    }
    
    void free2Darray(int** p, int N) {
        int i;
        for(i = 0 ; i < N ; i++)
            free(p[i]);
        free(p);
    }
    
    int** add_mat(int a[][2], int b[][2], int m, int n){
        int** c = get(n, m);
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                c[i][j]=a[i][j]+b[i][j];
            }
        }
        return c;
    }
    
    int main(){
    
        int n = 2, m = 2; //nxm of a matrix
        int a[n][m];
    
        read_mat(a, n, m);
    
        //add
        int b[n][m];
        read_mat(b, n, m);
        int** c;
        c = add_mat(a, b, n, m);
    
        print(c, n, m);
        free2Darray(c ,n);
    
        return 0;
    }
    

    输出:

    array[0][0] = 0
    array[0][1] = 2
    array[1][0] = 2
    array[1][1] = 4
    

    PPS:如果你真的想使用静态数组,那么我推荐使用int c[3][3]; add_mat(c, a, b, m, n);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      • 2021-12-26
      • 2019-04-30
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多