matrice statique et dynamique

matrice statique et dynamique - C - Programmation

Marsh Posté le 30-01-2007 à 21:21:57    

Bonsoir
 
Voilà je me retrouve confronté à un problème que je n'arrive pas à résoudre
 
le code suivant qui initialise et matrice sous cette forme
1    2    3
4    5    6
 
fonctionne que ce soit en statique ou en dynamique
statique
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main (void)
  4. {
  5.     int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
  6.    
  7.     int **p;
  8.    
  9.     p = a;
  10.    
  11.     return 0;
  12. }


 
dynamique

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main (void)
  4. {
  5.     int **a, **p;
  6.     int i, j, k;
  7.    
  8.     /* INITIALISATION MATRICE */
  9.    
  10.     a = malloc (2 * sizeof (int*));
  11.    
  12.     for (i = 0; i < 2; i++)
  13.         a[i] = malloc (3 * sizeof (int));
  14.        
  15.     k = 1;
  16.     for (i = 0; i < 2; i++)
  17.         for (j = 0; j < 3; j++)
  18.             a[i][j] = k++;
  19.            
  20.     p = a;     
  21.    
  22.     return 0;
  23. }


 
 
ensuite je dois faire des opérations sur cette matrice pour celà j'affecte un (int**)p sur (int**)a
 
 
le problème c'est qu'en statique mon compilo me met un warning quand je fais p = a alors qu'il ne me le fait pas en dynamique, et ça j'arrive pas à comprendre pourquoi
 
merci

Message cité 1 fois
Message édité par exhortae le 30-01-2007 à 23:49:17
Reply

Marsh Posté le 30-01-2007 à 21:21:57   

Reply

Marsh Posté le 30-01-2007 à 21:39:43    

Il faut faire une conversion de cast explicite :
p = (int **) a;
 
Le compilateur te met un warning parce que tu pourrais faire une connerie du genre "free(p);" dans la suite de ton programme. Là, tu lui montre que tu sais ce que tu fais.

Reply

Marsh Posté le 30-01-2007 à 21:53:00    

oki
 
maintenant voilà le problème qui se pose  
 
en statique quand je fais ensuite printf ("%d", **p);  le programme plante alors que ça ne plante pas en dynamique
 
 
statique

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main (void)
  4. {
  5.     int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
  6.    
  7.     int **p;
  8.    
  9.     p = (int**) a;
  10.    
  11.     printf ("%d", **p);
  12.    
  13.     system ("pause" );
  14.     return 0;
  15. }


 
http://img249.imageshack.us/img249/7659/plntjt0.jpg
 
 
 
dynamique

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main (void)
  4. {
  5.     int **a, **p;
  6.     int i, j, k;
  7.    
  8.     /* INITIALISATION MATRICE */
  9.    
  10.     a = malloc (2 * sizeof (int*));
  11.    
  12.     for (i = 0; i < 3; i++)
  13.         a[i] = malloc (3 * sizeof (int));
  14.        
  15.     k = 1;
  16.     for (i = 0; i < 2; i++)
  17.         for (j = 0; j < 3; j++)
  18.             a[i][j] = k++;
  19.            
  20.     p = a; 
  21.    
  22.     printf ("%d", **p);
  23.    
  24.     system ("pause" );   
  25.    
  26.     return 0;
  27. }


 
http://img59.imageshack.us/img59/9011/plnatepasez9.jpg
 

Reply

Marsh Posté le 30-01-2007 à 21:59:05    

Si tu comptes bien de 0 à 2 inclu il y a trois nombres, pas 2, donc ton a = malloc(2 * sizeof(int *)) est un peu faiblard. En plus tu ne vérifies pas le retour de malloc ce qui n'est jamais une bonne chose.

Reply

Marsh Posté le 30-01-2007 à 22:07:52    

Trap D a écrit :

Si tu comptes bien de 0 à 2 inclu . En plus tu ne vérifies pas le retour de malloc ce qui n'est jamais une bonne chose.


 
 
le 2 n'est pas inclu ;)
 
sinon j'ai juste pas mis de if (a == NULL) et if (a[i] == NULL) afin de montrer juste le strict minimum pour voir ce qui tourne pas, mais d'habitude je le mets tjs (ainsi que le free)

Reply

Marsh Posté le 30-01-2007 à 22:07:56    

dave_tetehi a écrit :

Il faut faire une conversion de cast explicite :
p = (int **) a;

 

Le compilateur te met un warning parce que tu pourrais faire une connerie du genre "free(p);" dans la suite de ton programme. Là, tu lui montre que tu sais ce que tu fais.

 

[:rofl]

 

en aucun cas 'a' ne peut être casté en (int **), c'est pas un tableau de pointeurs vers des tableaux d'entiers, c'est un tableau de tableaux d'entier.

Message cité 1 fois
Message édité par 0x90 le 30-01-2007 à 22:08:37

---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-01-2007 à 22:30:26    

Ah bon. Quelle différence y'a t-il entre un tableau de pointeur, et un tableau de tableau ? Je ne comprend pas pourquoi on ne peut pas faire ça. gcc -Wall -pedantic ne bronche pas.

Reply

Marsh Posté le 30-01-2007 à 22:33:04    

dave_tetehi a écrit :

Ah bon. Quelle différence y'a t-il entre un tableau de pointeur, et un tableau de tableau ? Je ne comprend pas pourquoi on ne peut pas faire ça. gcc -Wall -pedantic ne bronche pas.


 
Dessine la mémoire tu va bien voir la différence ... (ou alors ouvre un bouquin de C...)


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 30-01-2007 à 22:43:48    

Je me trompe surement, mais le tableau statique est alloué dans le segment data, peut importe le nombre de dimension, l'allocation est faite de manière continue, nen ? desolé, si je suis dur d'oreille, mais je comprend tjs pas.

Reply

Marsh Posté le 30-01-2007 à 22:56:06    

Excuse moi d'insister mais quand je vois

Code :
  1. // tu alloues la place pour 2 pointeur vers des entiers
  2. a = malloc(2 * sizeof (int*));
  3. // Tu en affectes trois a[0], a[1] et a[2]
  4. for (i = 0; i < 3; i++)
  5.         a[i] = malloc (3 * sizeof (int));

Je me dis qu'il y a un problème et que ça peut fonctionner quelques fois, mais ça risque tout de même de planter un jour.

Reply

Marsh Posté le 30-01-2007 à 22:56:06   

Reply

Marsh Posté le 30-01-2007 à 23:47:40    

0x90 a écrit :

Dessine la mémoire tu va bien voir la différence ... (ou alors ouvre un bouquin de C...)


 
Effectivement je me suis bien planté, je pense que ce genre de chose est beaucoup plus propre :

Code :
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int i;
  5. int a[4][5];
  6. int * b;
  7. b = (int *) a;
  8. printf("%p\n", (void *) a);
  9. printf("%p\n\n", (void *) b);
  10. for(i=1; i < 21; i++)
  11.  *(b++) = i;
  12. printf("%d\n", a[0][0]);
  13. printf("%d\n", a[1][0]);
  14. printf("%d\n", a[2][0]);
  15. printf("%d\n", a[3][0]);
  16. return 0;
  17. }

Reply

Marsh Posté le 30-01-2007 à 23:48:58    

Trap D a écrit :

Excuse moi d'insister mais quand je vois

Code :
  1. // tu alloues la place pour 2 pointeur vers des entiers
  2. a = malloc(2 * sizeof (int*));
  3. // Tu en affectes trois a[0], a[1] et a[2]
  4. for (i = 0; i < 3; i++)
  5.         a[i] = malloc (3 * sizeof (int));

Je me dis qu'il y a un problème et que ça peut fonctionner quelques fois, mais ça risque tout de même de planter un jour.


 
 
oui tu as raison, juste une erreur d'innatention, je corrige ça tout de suite, merci

Reply

Marsh Posté le 30-01-2007 à 23:52:51    

0x90 a écrit :

[:rofl]
 
en aucun cas 'a' ne peut être casté en (int **), c'est pas un tableau de pointeurs vers des tableaux d'entiers, c'est un tableau de tableaux d'entier.


 
 
je vois ce que tu veux dire, mais je n'arrive pas à visualiser la différence au niveau mémoire, tu aurais un lien qui explique tout ça

Reply

Marsh Posté le 31-01-2007 à 00:23:48    

dave_tetehi a écrit :

Effectivement je me suis bien planté, je pense que ce genre de chose est beaucoup plus propre :

Code :
  1. int a[4][5];
  2. int * b;
  3. b = (int *) a;



 [:arrakys] Mais c'est quoi ce cast de la mort qui tue ? Tu ne sais pas écrire du C correct ?


---------------
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 31-01-2007 à 00:25:19    

exhortae a écrit :

je vois ce que tu veux dire, mais je n'arrive pas à visualiser la différence au niveau mémoire, tu aurais un lien qui explique tout ça


Dessine ce qui se passe avec les pointeurs. C'est à toi de le faire, personne ne peut le faire a ta place. Et désolé si tu grilles trois neurones en faisant ça, mais c'est indispensable...

 

Message cité 1 fois
Message édité par Emmanuel Delahaye le 31-01-2007 à 00:25:41

---------------
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 03-02-2007 à 05:15:48    

Emmanuel Delahaye a écrit :

Dessine ce qui se passe avec les pointeurs. C'est à toi de le faire, personne ne peut le faire a ta place. Et désolé si tu grilles trois neurones en faisant ça, mais c'est indispensable...


 
 
Voilà comment je vois ça, si quelqu'un pourrais me dire si c'est bon je pourrais expliquer ensuite comment je vois la chose.
 
Merci
 
 
http://img128.imageshack.us/img128/7986/tableauxao2.jpg
 
 
 
PS : ça ma coûté mes 6 derniers neuronnes  :sweat:

Message cité 1 fois
Message édité par exhortae le 03-02-2007 à 05:16:48
Reply

Marsh Posté le 03-02-2007 à 13:22:01    

exhortae a écrit :

Bonsoir
 
Voilà je me retrouve confronté à un problème que je n'arrive pas à résoudre
 
le problème c'est qu'en statique mon compilo me met un warning quand je fais p = a alors qu'il ne me le fait pas en dynamique, et ça j'arrive pas à comprendre pourquoi
 
merci


 
Va ici http://forum.hardware.fr/hfr/Progr [...] 0049_1.htm relire mon post du 9 janvier dernier. Il s'agit de la même question !!!!
 
La partie importante qui ne t'as probablement pas sautée aux yeux est celle-ci "Le pb du débutant, c'est qu'il a tendance à croire que [] <=> * donc [][] <=> **  
L'équivalence n'est vrai que pour une seule dimension. Pourquoi ? parce que la mémoire n'est définie, en mémoire, que sur une seule dimension. Les cases mémoires sont alignées sur une seule et immense ligne
."
 

exhortae a écrit :

Voilà comment je vois ça, si quelqu'un pourrais me dire si c'est bon je pourrais expliquer ensuite comment je vois la chose.
http://img128.imageshack.us/img128/7986/tableauxao2.jpg


Un tableau de tableaux style "int tab[2][3]={{1, 2, 3}, {4, 5, 6}}" se présente ainsi

Citation :


adresse     xxx          0x1000      0x1004        0x1008        0x100c      0x1010        0x1014
nom          tab        tab[0][0]   tab[0][1]     tab[0][2]     tab[1][0]   tab[1][1]     tab[1][2]
contenu   0x1000          1              2                3                4              5                 6


 
Un tableau de pointeurs, style "int **tab" (avec les malloc qui vont bien) se présente ainsi

Citation :


adresse     xxx          0x1000      0x1004    
nom          tab          tab[0]      tab[1]    
contenu   0x1000      0x5000      0x7120
 
adresse     0x5000     0x5004      0x5008    
nom         tab[0][0]  tab[0][1]   tab[0][2]
contenu        1             2              3
 
adresse     0x7120     0x7124      0x7128
nom         tab[1][0]  tab[1][1]   tab[1][2]
contenu         4            5               6

Message cité 1 fois
Message édité par Sve@r le 03-02-2007 à 14:18:05

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 05-02-2007 à 08:51:09    

Sve@r a écrit :

Va ici http://forum.hardware.fr/hfr/Progr [...] 0049_1.htm  
 
Un tableau de tableaux style "int tab[2][3]={{1, 2, 3}, {4, 5, 6}}" se présente ainsi
 

Citation :


adresse     xxx          0x1000      0x1004        0x1008        0x100c      0x1010        0x1014
nom          tab        tab[0][0]   tab[0][1]     tab[0][2]     tab[1][0]   tab[1][1]     tab[1][2]
contenu   0x1000          1              2                3                4              5                 6  


 
 


 
en faite ce que je n'arrive pas à comprendre quand je vois cette présentation c'est pourquoi quand je fais tab + 1, il part à l'adresse 0x100c (c'est à dire vers le 2ème tableau, au lieu d'aller à l'adresse 0x1004.
 
j'ai compris que pour le faire il faut faire  
 

Code :
  1. int *p;
  2. p = (int*) tab;


 
puis on peux faire *(p + 1) pour acceder à la case tab[0][1], mais je ne vois pas pourquoi tab + 1 ne serait pas égale à 0x1004.
 
sinon j'avais bien lu ta réponse dans le post du 9 janvier mais le problème c'est qu'en c il utilise tab[i][j] pour tab[..][..] ou **tab et ça ça me perturbe toujours un peu
 
merci.

Message cité 1 fois
Message édité par exhortae le 05-02-2007 à 08:54:33
Reply

Marsh Posté le 05-02-2007 à 22:13:46    

exhortae a écrit :

en faite ce que je n'arrive pas à comprendre quand je vois cette présentation c'est pourquoi quand je fais tab + 1, il part à l'adresse 0x100c (c'est à dire vers le 2ème tableau, au lieu d'aller à l'adresse 0x1004.
 
j'ai compris que pour le faire il faut faire  
 

Code :
  1. int *p;
  2. p = (int*) tab;


 
puis on peux faire *(p + 1) pour acceder à la case tab[0][1], mais je ne vois pas pourquoi tab + 1 ne serait pas égale à 0x1004.


TU N'AS PAS LE DROIT DE COPIER tab DANS p => ce ne sont pas des variables de même type

  • p est de type "int étoile"
  • tab peut être vu comme un type "int étoile étoile" bien que ce ne soit pas la réalité (c'est juste une illustration pour montrer qu'il y a 2 indirections)

En tout cas un type "int étoile" n'est pas un type "int étoile étoile". C'est d'ailleurs pour ça que tu fais un cast => parce que ton compilo râle !!!
Il s'ensuit qu'ensuite il essaye de s'en sortir avec ce qu'il peut et te donne un résultat un peu batard
Essaye d'ailleurs, juste pour voir, d'afficher "tab" avec "%p" et d'afficher aussi "*tab" avec "%p"...
 

exhortae a écrit :

sinon j'avais bien lu ta réponse dans le post du 9 janvier mais le problème c'est qu'en c il utilise tab[i][j] pour tab[..][..] ou **tab et ça ça me perturbe toujours un peu


Parce que tu cherches à assimiler [][] à "étoile étoile" alors que ce n'est pas le cas.

Message cité 1 fois
Message édité par Sve@r le 05-02-2007 à 22:16:01

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 05-02-2007 à 23:22:10    

Sve@r a écrit :

TU N'AS PAS LE DROIT DE COPIER tab DANS p => ce ne sont pas des variables de même type

  • p est de type "int étoile"
  • tab peut être vu comme un type "int étoile étoile" bien que ce ne soit pas la réalité (c'est juste une illustration pour montrer qu'il y a 2 indirections)

En tout cas un type "int étoile" n'est pas un type "int étoile étoile". C'est d'ailleurs pour ça que tu fais un cast => parce que ton compilo râle !!!
Il s'ensuit qu'ensuite il essaye de s'en sortir avec ce qu'il peut et te donne un résultat un peu batard


 
Dans ce cas là est-ce que je peux utiliser la formule suivante :  
 

Code :
  1. scanf ("%d", (int*) a + 1);


 

Sve@r a écrit :


Essaye d'ailleurs, juste pour voir, d'afficher "tab" avec "%p" et d'afficher aussi "*tab" avec "%p"...


 
Elles ont la même valeur, je l'avais remarqué lors de mes expérimentations ;)
 
par contre son explication  reste un mystère pour moi, est-ce que ça veut dire que tab pointe sur tab  :??:
 
et là à bien y penser j'aurais plutôt utilisé  

Code :
  1. scanf ("%d", *a + 1);


 
bref je suis perdu...

Message cité 1 fois
Message édité par exhortae le 05-02-2007 à 23:28:20
Reply

Marsh Posté le 06-02-2007 à 10:50:07    

exhortae a écrit :

par contre son explication  reste un mystère pour moi, est-ce que ça veut dire que tab pointe sur tab  :??:


Ca veut dire que si l'équivalence entre "int[]" et "int *" est vraie, l'équivalence entre "int[][]" et "int **" ne l'est pas. On peut éventuellement essayer de la faire dans un but très très illustratif mais seulement dans ce but là et non dans des termes d'égalité mathématique.
Donc si t'essayes de la faire, tu obtiendras des résultats incohérents avec ton raisonnement...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 06-02-2007 à 14:17:02    

Sve@r a écrit :

Ca veut dire que si l'équivalence entre "int[]" et "int *" est vraie, l'équivalence entre "int[][]" et "int **" ne l'est pas. On peut éventuellement essayer de la faire dans un but très très illustratif mais seulement dans ce but là et non dans des termes d'égalité mathématique.
Donc si t'essayes de la faire, tu obtiendras des résultats incohérents avec ton raisonnement...


 
Syntaxiquement ça passe la plupart du temps, mais c'est pas exactement vrai, gaffe aux sizeofs ;)


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 07-02-2007 à 17:11:31    

0x90 a écrit :

Syntaxiquement ça passe la plupart du temps, mais c'est pas exactement vrai, gaffe aux sizeofs ;)


Ah ? On peut avoir des problèmes si on utilise de façon équivalente "tab[x]" et "*(tab + x)" ???


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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