使用指针添加2个矩阵

时间:2017-10-01 13:03:51

标签: c arrays function pointers multidimensional-array

我可以通过将(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;
}

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

3 个答案:

答案 0 :(得分:2)

你不能这样做,因为当函数终止时c矩阵的记忆将消失。

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

使用上一个函数,您可以在函数外部创建矩阵c(在main()中),这就是不需要动态内存分配的原因。

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

答案 1 :(得分:1)

哦,是的,指针......

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

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

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

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

其次,您的行int* c[3][3];可能不是您想要的那样。您在这里声明c指向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);

答案 2 :(得分: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);