Manipulation de matrices, Allocation dynamique...

Manipulation de matrices, Allocation dynamique... - C - Programmation

Marsh Posté le 15-02-2007 à 16:16:54    

Salut,
J'ai un problème (à l'exécution) avec un petit code qui manipule des matrices allouer dynamiquement, et je ne comprend pas d'où est ce que l'erreur peut elle venir !
voici le code source (incomplet pour l'instant):

Code :
  1. void Allocate_Memory(int **A, int N, int M)
  2. {
  3.     int i;
  4.     A = (int**) malloc(sizeof(int*) * N);
  5.     for(i=0; i<N; i++)
  6.         A[i] = (int*) malloc(sizeof(int) * M);
  7. }


 
Merci pour votre aide.

Message cité 2 fois
Message édité par bad___day le 24-02-2007 à 13:08:42
Reply

Marsh Posté le 15-02-2007 à 16:16:54   

Reply

Marsh Posté le 15-02-2007 à 17:55:30    

bad___day a écrit :

voici le code source (incomplet pour l'instant):


Déjà ça, ça craint...


Project   : Forums
Compiler  : GNU GCC Compiler (called directly)
Directory : C:\dev\forums2\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.c
main.c: In function `Sous_Menu':
main.c:183: warning: control reaches end of non-void function
main.c: In function `main':
main.c:22: warning: 'matrice1' might be used uninitialized in this function
main.c:22: warning: 'matrice2' might be used uninitialized in this function
Linking console executable: console.exe
Process terminated with status 0 (0 minutes, 5 seconds)
0 errors, 3 warnings


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 15-02-2007 à 18:09:47    

Pour le warning main.c:183: warning: control reaches end of non-void function
Ce n'ai pas bien grave car je n'ai pas besoin de retourné quoi que ce soit a la fin de la fonction,
puisque je retourne obligatoirement quelque chose dans mes switch() et que j'ai fait un controle de saisi.
 
Pour les deux autre warning, je ne saisi pas  :sweat:  , car je n'ai pas besoin de les initialisé, je passe les adresse a la fonction qui fait l'allocation !
 
NB: Ne pas regarder l'utilisation de scanf() , car c'est juste pour les essayes..
 
 

Reply

Marsh Posté le 15-02-2007 à 18:14:48    

Citation :


    A = (int**) malloc(sizeof(int*) * N);
    for(i=0; i<N; i++)
        A[i] = (int*) malloc(sizeof(int) * M);


 
On ne caste pas un malloc :o

Reply

Marsh Posté le 15-02-2007 à 18:15:27    

dave_tetehi a écrit :

On ne caste pas un malloc :o


Ok :) , mais ça ne change pas grand chose au prob. lol

 


Message édité par bad___day le 15-02-2007 à 18:16:30
Reply

Marsh Posté le 15-02-2007 à 18:20:58    

Citation :


            case 11:
            {
                int N, M;
                printf("Donnez la dimmantion des matrices:\n" );
                printf("Nombre de ligne:  " );
                scanf("%d", &N);
                printf("Nombre de colonne:  " );
                scanf("%d", &M);
                Allocate_Mat_Memory(matrice1, N, M);
                Allocate_Mat_Memory(matrice2, N, M);
                Saisi_Mat(matrice1, N, M);
                Saisi_Mat(matrice2, N, M);
                //Add_Soust_Mat( '+', matrice1, matrice2, N, M);
                //Affiche_Mat(matrice1, N, M);
                //Free_Mat_Memory(matrice1, N);
                //Free_Mat_Memory(matrice2, N);
            }
            break;
 
            case 12:
                //Add_Soust_Mat( '-', matrice1, matrice2, N, M);


 
Il ne faut pas initialiser N, M dans le bloc case 11, si vous compter les utiliser dans le bloc case 12.

Reply

Marsh Posté le 15-02-2007 à 18:24:56    

dave_tetehi a écrit :

Il ne faut pas initialiser N, M dans le bloc case 11, si vous compter les utiliser dans le bloc case 12.


je vais les réinitialiser dans ce cas... a chaque bloc, car ce n'ai pas les même dimensions que l'utilisateur dois utilisé a chaque case...

 


De toute façons, le probléme qui apparés a l'execution n'ai pas à cause de ça ... !

 



Message édité par bad___day le 15-02-2007 à 18:28:04
Reply

Marsh Posté le 15-02-2007 à 18:28:30    

De plus votre allocation est fausse.
 

Citation :


void Allocate_Mat_Memory(int **A, int N, int M)
{
    int i;
 
    A = (int**) malloc(sizeof(int*) * N);
    for(i=0; i<N; i++)
        A[i] = (int*) malloc(sizeof(int) * M);
 
}


 
Vous êtes en train allouer de la mémoire pour une variable automatique qui va être détruite à la fin de la portée.
 
Pour faire ce que vous voulez faire, il faut passer en parmètre l'adresse du pointeur de pointeur.
 
 
Allocate_Mat_Memory( &matrice1, N, M);
 
avec un prototype comme ceci :
 
void Allocate_Mat_Memory(int ***A, int N, int M)

Reply

Marsh Posté le 15-02-2007 à 18:34:14    

Le compilateur avait raison, il y a bien un bug...


main.c:22: warning: 'matrice1' might be used uninitialized in this function
main.c:22: warning: 'matrice2' might be used uninitialized in this function


Il faut toujours écouter son compilateur...
 

bad___day a écrit :


Code :
  1. int main(void)
  2. {
  3.     int **matrice1, **matrice2;
  4.        <...>
  5.                 Allocate_Mat_Memory(matrice1, N, M);
  6.                 Allocate_Mat_Memory(matrice2, N, M);




Problème récurrent. Si on veut qu'une fonction modifie la valeur d'une variable, il faut passer l'adresse de la variable via un paramètre pointeur du bon type ou retourner la valeur (beaucoup plus clair, parce que les ***, non merci...)...
 
http://mapage.noos.fr/emdel/notes. [...] e_variable
 
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 15-02-2007 à 18:52:49    

Citation :


A = (int**) malloc(sizeof(int*) * N);  
    for(i=0; i<N; i++)  
        A[i] = (int*) malloc(sizeof(int) * M);


 
D'ailleurs, ce n'est pas toujours la meilleur façon d'allouer la mémoire, rien ne vous garantit que votre mémoire sera allouée de façon contigu.
Après, tout dépend de ce que vous voulez en faire, mais bien souvent, un tableau (ex, une image) = balayage ligne par ligne, donc si c'est votre cas, cette méthode d'allocation est à bannir, je préconise plutot quelque chose de ce genre. Après, si votre mémoire est limitée, ou si votre matrice est vraiment très volumineuse, il faut mieux la segmenter, donc restez sur votre position.  :whistle:  

Code :
  1. int ** A = malloc(sizeof(int *) * N);
  2. int  * B = malloc(sizeof(int) * N*M);
  3. for(i=0; i < N; i++)
  4. {
  5. A[i] = B;
  6. B += M;
  7. }


Reply

Marsh Posté le 15-02-2007 à 18:52:49   

Reply

Marsh Posté le 15-02-2007 à 19:07:07    

Salut,
 
en général la fonction d'init d'un pointeur (sur variable simple, tableau, matriceXd, objet) retourne l'adresse d'un bloc mémoire qu'elle vient d'allouer,
alors que toi tu fais :

Code :
  1. void Allocate_Mat_Memory(int **A, int N, int M)

càd que tu renvoie que dalle...
 
Ya également la possibilité, comme le précise Emmanuel Delahaye, et comme tu l'as fait mais mal, de passer directement l'adresse de ton pointeur à la fonction d'init, c'est pratique dans certains cas, mais bon là typiquement il faut créer ton pointeur dans la fonction d'init, l'allouer, et le renvoyer à ton pointeur du même type, simplement déclaré au préalable et donc vide, dans ton main.
C'est généralement la bonne solution, et pour toi c'est important de le faire comme ça au début, ça va t'éclaircir les idées au lieu de t'embrouiller.
 
Pour t'aider à bien réaliser le truc, tu peux penser à l'init d'un pointeur comme on le fait en C++ :

Code :
  1. int * a;
  2. a = new(int);

Sauf que la tu "recodes" le new() à la main (et en C), mais le principe est le même : d'abord tu déclares un pointeur vide, et après tu lui appliques une fonction d'allocation mémoire, qui retourne le pointeur sur le bloc mémoire alloué.
 
Et aussi : printf() est ton amie :hello: T'en place quelques-uns à des endroits judicieux de ton code, comme ça tu sais où ça coince...
 
 
Edit
A propos de la remarque de dave_tetehi : faut po l'écouter :whistle: C'est déjà de l'optimisation alors que visiblement tu n'en es qu'à la phase d'apprentissage, et c'est trétrémal de mixer les 2 ensemble à ce stade...
Si tu regardes il additionne même un nombre entier à un pointeur quand il écrit B += M; ce qui fait avancer le pointeur dans ton tableau de M cases mémoire car tab[a] <=> *(tab+a) => (tab+a) est l'adresse de tab[a]. Bref, c'est pas nécessaire point de vue pédagogique, sauf si on l'explique hein :p
Enfin la manière dont sont ordonnés les blocs mémoire peut être importante voire primordiale, mais ici osef, d'autant plus que quand on veut vraiment optimiser un calcul matriciel pas trop énorme on utilise un vecteur et on joue directement avec les indices pour "simuler" une matrice :ange:


Message édité par lkolrn le 16-02-2007 à 05:15:50
Reply

Marsh Posté le 17-02-2007 à 10:19:18    

il faut utiliser une boucle for

Reply

Marsh Posté le 17-02-2007 à 10:26:45    

k lol.

Reply

Marsh Posté le 17-02-2007 à 15:24:44    

Je préfère récupérer la valeur retournée par ma fonction ( sans avoire à utilisé les *** ,  comme dit Emmanuel: retourner la valeur c'est beaucoup plus clair, parce que les ***, non merci... )
Mais dans ce cas comment je fait pour ma fonction Free_Mat_Memory() ?
Est ce que je suis obligé d'utiliser ***
 

Reply

Marsh Posté le 17-02-2007 à 21:54:55    

A la limite on s'en fout de "préférer" ou pas, c'est comme ça que ça marche généralement, à ce stade (le tien) au moins :
quand on alloue de la mémoire, on retourne une adresse et on l'affecte à un pointeur vide du type correspondant.
 
Tu verras dans peu de temps comment faire avec l'adresse (d'un pointeur ici) passée en paramètre à la fonction d'allocation, mais pour l'instant il ne faut même pas le prendre en compte, tu sais que c'est une autre solution possible, point. Commencer par le commencement quoi...
 
Sinon, pour répondre à ta question sur la libération de la mémoire : tu passes directement ton pointeur à ta fonction, pas besoin d'ajouter un niveau d'indirection supplémentaire (càd l'adresse de ce pointeur). Par contre, il faut être vigileant à bien désallouer tout ce qui a été précédemment alloué, càd traiter chaque pointeur sur bloc mémoire, dans le sens contraire de l'allocation.
En gros, la fonction Free_Mat() est la correspondance contraire de Allocate_Mat(), chaque pointeur initialisé (par malloc ici) dans Allocate_Mat() selon un certain ordre doit être libéré dans Free_Mat(), selon l'ordre contraire.
C'est très logique, pour construire une pile d'assiettes on pose la première, puis la deuxième par dessus, etc... Et pour la détruire proprement on retire la dernière, celle en haut de la pile, puis l'avant-dernière, etc...
 
Donc là, de la même façon, pour créer ta matrice tu as d'abord créé un vecteur/tableau, sa "1ère ligne", et dans chaque case de ton vecteur tu as mis un pointeur sur un autre tableau, équivalent à chaque "colonne" de la matrice.
Dans l'autre sens maintenant, pour supprimer ta matrice, tu commences par free() chaque "colonne" de ta matrice, et pour finir tu libères la "1ère ligne".
 
 
 
PS : énorme le davidenko... [:skyx@v]  
 

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed