2017-10-01 6 views
2

je peux atteind par le passage (c,a,b) à la fonction add_mat, où résultat de a,b est stocké dans c comme,Ajout 2 matrices à l'aide des pointeurs

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

Quel devrait être le type de retour add_mat si je veux construire le funtion de cette façon

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

est inférieur à un exemple de code

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

Comme passant ou en pointant la valeur calculée c intérieur add_mat fonction de variable dans main fonction.

+0

Je propose 'int c [3] [3]; add_mat (c, a, b, m, n); ' – BLUEPIXY

Répondre

2

Vous ne pouvez pas faire cela, car la mémoire de la matrice c aura disparu lorsque la fonction se termine.

Vous devez allouer dynamiquement avec malloc(), pour que la mémoire ne doit pas être free'd, à moins que vous appel free(). J'ai quelques exemples pour cela dans 2D dynamic array (C), si vous voulez jeter un coup d'oeil.

Avec votre fonction précédente, vous créiez la matrice c en dehors de la fonction (dans main()), c'est pourquoi l'allocation de mémoire dynamique n'était pas requise.


PS: Vous devez compiler des avertissements activés:

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]; 
     ^

Voici un exemple de travail, qui est juste à des fins démonstratives:

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

Sortie:

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

PPS: Si vous voulez vraiment utiliser des tableaux statiques, alors je recommande d'utiliser int c[3][3]; add_mat(c, a, b, m, n);

1

Oh oui, les pointeurs ...

En C, généralement déclarés localement des tableaux sont attribués sur la pile (pas le tas) ce qui signifie qu'ils ne sont pas valides en dehors de la portée respective. En d'autres termes, dans votre fonction add_mat(), c peut techniquement être renvoyée, mais l'adresse vers laquelle elle pointe ne contiendra que des données matricielles significatives tant que la fonction est exécutée.

Après retour de la fonction, la valeur de retour de la fonction est un pointeur qui contient encore (points) Le adresse où la matrice a été stockée lors de l'exécution de la fonction, mais les contenu de ce emplacement, à savoir les données de la matrice, peuvent contenir des ordures arbitraires maintenant.

Donc ce que vous faites est techniquement possible (c'est-à-dire ne génère aucune erreur de compilation), mais ce n'est certainement pas ce que vous voulez.

Deuxièmement, votre ligne int* c[3][3]; n'est probablement pas ce que vous voulez qu'elle soit. Vous déclarez c être un tableau bidimensionnel (matrice) de pointeur vers int ici. Ceci n'est pas correct puisque vous voulez traiter les valeurs int, mais pas les pointeurs à int valeurs (qui sont des adresses).

Pour résoudre les problèmes, il suffit d'écrire int c[3][3]; au lieu de int* c[3][3]; et changer votre fonction add_mat() comme suit:

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

appellent ensuite cette fonction comme ça:

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

c'est pourquoi je passais' c, a, b' pour fonctionner .. belle explication pour savoir ce qui se passe dans le capot .. @gsamaras répondu selon mon utilisation Cas. –

+0

Merci. Si mon explication vous a été utile, alors pourquoi ne pas upvote :-) – Binarus

1

Dans votre code add_mat renvoie la pointeur vers la variable qui vit alors que la fonction s'exécute seulement. Vous pouvez accomplir votre objectif avec une matrice allouée dynamiquement.

En C, il est courant de transmettre une matrice allouée dynamiquement via pointeur vers des pointeurs vers les lignes de la matrice en tant que premier paramètre:

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

Ici matrix est un pointeur sur le tableau de pointeurs. Chaque pointeur de ce tableau pointe vers la ligne de la matrice. Ainsi, matrix[0] pointe vers le tableau contenant la première ligne de la matrice.

Et il est courant d'utiliser le type size_t pour toutes les tailles de matrices.

Si vous avez besoin de créer une matrice dynamiquement, faites attention à la mémoire. Chaque bloc alloué dynamiquement devrait être libéré. Sinon, vous aurez des fuites de mémoire, ce qui pourrait causer le crash du programme. Par conséquent, lorsque vous allouez des lignes de matrice, vous devez vérifier si l'allocation de la ligne actuelle a réussi. Si ce n'est pas le cas, vous devez libérer toutes les lignes précédemment allouées.

Il y a un code de travail pour votre question:

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

Mais vous serait plus souple, si add_mat n'a pas créé une nouvelle matrice. Il est fréquent de passer un pointeur vers la matrice de résultat en tant que paramètre de fonction:

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