[c] Passer l'adresse d'un tableau a 2 dim en parametre [OK]

Passer l'adresse d'un tableau a 2 dim en parametre [OK] [c] - C - Programmation

Marsh Posté le 26-04-2004 à 15:42:16    

Bonjour,
j'essaye de passer l'adresse d'un tableau à 2 dimensions en paramètre de ma fonction mais je n'y arrive point.
 
dans mon main, j'ai une variable :

Code :
  1. int Vector[10][10];


j'appelle ma fonction ainsi :

Code :
  1. Fonction(&Vector);


 
et ma fonction est déclarée comme suit :

Code :
  1. void Fonction (int *** Vector){ ... }


 
A la compilation, j'ai cette erreur là :
orion > gcc -o label SpectralRouting.c
SpectralRouting.c: In function `main':
SpectralRouting.c:62: warning: passing arg 1 of `Fonction' from incompatible pointer type
 
Donc je ne comprend pas d'où vient mon erreur ...
Pourtant en c, l'adresse d'un tableau d'entiers à 2 dimensions, c'est bien un int *** non ????  
 
Merci des réponses  :sleep:


Message édité par fif_x le 27-04-2004 à 10:44:54
Reply

Marsh Posté le 26-04-2004 à 15:42:16   

Reply

Marsh Posté le 26-04-2004 à 15:52:31    

Un programme en C, c'est comme un ciel d'été : c'est plein d'étoiles


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 26-04-2004 à 15:59:30    

:lol:
c sympa, mais ça m'aide pas beaucoup :)
 
J'ai mis trop d'étoiles dans mon ciel ?? heu, dans mon programme ??

Reply

Marsh Posté le 26-04-2004 à 16:18:57    

Gros Doute :
 
si je fait

Code :
  1. Fonction (Vector);


 
avec une fonction

Code :
  1. void Fonction (int **Vector)


 
ça me passe une copie tu tableau ou bien l'adresse du 1er élément du tableau ???

Reply

Marsh Posté le 26-04-2004 à 16:43:33    

J'ai trouvé une solution en faisant :
 

Code :
  1. void Fonction (int * Vector){...}


et

Code :
  1. Fonction (&Vector[0][0]);


 
Mais dans ma fonction, je ne peux plus faire  
 
 

Code :
  1. int *a;
  2. a = Vector[1][1];


 
gcc me sort à la compilation : subscripted value is neither array nor pointer
 
je ne comprend plus ...
Le passage du tableau en parametre est-il bon ???
 
Merci.

Reply

Marsh Posté le 26-04-2004 à 17:15:02    

void Fonction (int* Vector)
...
Fonction(Vector)
?


---------------
blog dessins + srtCleaner | Ricoh R6 | K20d | MK-wii 5112-3549-9484 | en phase de déblablatisation depuis le 26 avril 2002 | Belgian Connection
Reply

Marsh Posté le 26-04-2004 à 17:21:46    

non désolé ce n'est pas ça, le compilateur me dit toujours passing arg 1 of `Fonction' from incompatible pointer type  
 
 
Merci quand meme :)

Reply

Marsh Posté le 26-04-2004 à 17:46:44    

Lors du passage en paramètre d'un tableau à 2 dimensions le compilateur perd la taille de la dimension 2, qui est pourtant indispensable pour indexer correctement le tableau (car un tableau à deux dimensions, en mémoire, est "tout plat" ). Donc il y a plusieures manières de faire, par exemple :

Code :
  1. void foo1(int t[])
  2. /*
  3. dans ce contexte, c'est équivalent à :
  4. void foo1(int *t)
  5. */
  6. {
  7.    /* Accès par t[0] ... t[9] */
  8.    /* J'ai un doute que ce soit bien défini, mais logiquement oui */
  9. }
  10. void foo2(int t[][2])
  11. /*
  12. dans ce contexte, c'est équivalent à :
  13. void foo2(int (*t)[2])
  14. */
  15. {
  16.    /* Accès par t[0][0] ... t[4][1] */
  17. }
  18. void foo3(int *t, int d)
  19. {
  20.    /* Pour accéder l'élément t[i][j] :
  21.    
  22.    *(t + i * d + j)
  23.    
  24.    */
  25. }
  26. int main(void)
  27. {
  28.    int t[5][2];
  29.  
  30.    foo1(t[0]);
  31.    foo1(&t[0][0]);
  32.    foo2(t);
  33.    foo3(&t[0][0], 2);
  34.  
  35.    return 0;
  36. }


Message édité par djdie le 26-04-2004 à 17:47:58
Reply

Marsh Posté le 26-04-2004 à 17:54:11    

Allez, soyons fou, je rajouterais même foo4 : :D

Code :
  1. int foo4(int* t, size_t l, size_t c)
  2. {
  3. /* Pour accéder l'élément t[i][j] */
  4. t[(i * c) + j]
  5. ...
  6. return 0;
  7. }

Ce qui permet, une fois à l'intérieur de la fonction, de connaître le nombre de lignes (l) et le nombre de colonnes (c).
Bon ce coup-ci c'est tout propre ! :D


Message édité par darkoli le 27-04-2004 à 08:34:43
Reply

Marsh Posté le 26-04-2004 à 18:37:32    

pour les dimensions, utilisez le type prévu pour : size_t

Reply

Marsh Posté le 26-04-2004 à 18:37:32   

Reply

Marsh Posté le 26-04-2004 à 23:05:48    

Pour passer un tableau 2D suffit de faire :

Code :
  1. void fonction(int** tab);


 
puis

Code :
  1. fonction(tab[][N]);


 

Reply

Marsh Posté le 26-04-2004 à 23:10:49    

kmikaz92 a écrit :

Code :
  1. fonction(tab[][N]);




Hum c'est déjà syntaxiquement faux...
 
Je crois que toutes les solutions "raisonnables" ont été données plus haut (si ce n'est qu'il aurait été en effet mieux d'utiliser size_t).

Reply

Marsh Posté le 26-04-2004 à 23:29:35    

Oops me croyait en PHP en fait :) Et encore je sais pas si ca marche en PHP mais je me souviens l'avoir fait...
Pour le size_t, c'est juste un typedef de unsigned... je pense pas que ca fasse bugger le programme. Mais il est mieux de l'utiliser oui.

Reply

Marsh Posté le 27-04-2004 à 09:10:08    

Merci de toutes les réponses, c'est vraiment sympa :)
A+

Reply

Marsh Posté le 27-04-2004 à 09:16:30    

plutôt que d'essayer de rajouter une * par là, ajouter un & par là, vaudrait mieux relire le chapitre sur les pointeurs

Reply

Marsh Posté le 27-04-2004 à 10:01:14    

Alors j'ai testé un peu toute les solutions, elles marchent bien.
Mais pour mon second probleme qui était d'assigner l'adresse d'une case du tableau a une variable :
 

Code :
  1. int *ptr;
  2. ptr = tab[i][j]


j'avais une erreur de compilation.
 
J'ai réussi a contrer le problème en fesant :

Code :
  1. void foo3(int *tab, int d)
  2. {
  3. int *ptr;
  4. ptr = (tab + i * d + j);
  5. }


 
et ça marche très bien.
Merci à tous :jap: :jap: :jap: :jap:


Message édité par fif_x le 27-04-2004 à 10:01:54
Reply

Marsh Posté le 27-04-2004 à 10:05:06    

Code :
  1. ptr = &tab[i][j];

?

Reply

Marsh Posté le 27-04-2004 à 10:43:57    

oui, ça te parait peut-etre stupide. Et c'est surement pour ça que ça ne marchait pas :D

Reply

Marsh Posté le 27-04-2004 à 11:28:45    

non non, regarde, j'ai rajouté un "&"

Reply

Marsh Posté le 27-04-2004 à 11:52:00    

HelloWorld a écrit :

Code :
  1. ptr = &tab[i][j];

?

et il les connait comment les dimensions ton compilateurs ?

Reply

Marsh Posté le 27-04-2004 à 14:30:52    

Citation :

Mais pour mon second probleme qui était d'assigner l'adresse d'une case du tableau a une variable :  
 
 
Code :
 
  int *ptr;  
  ptr = tab[i][j]  
   
 
 
j'avais une erreur de compilation.  

Reply

Marsh Posté le 27-04-2004 à 14:50:21    

HelloWorld a écrit :

Citation :

Mais pour mon second probleme qui était d'assigner l'adresse d'une case du tableau a une variable :  
 
 
Code :
 
  int *ptr;  
  ptr = tab[i][j]  
   
 
 
j'avais une erreur de compilation.  




 
ça m'étonne pas...

Reply

Marsh Posté le 27-04-2004 à 16:28:14    

HelloWorld a écrit :

non non, regarde, j'ai rajouté un "&"


 
Meme avec un '&' le compilateur ne voulait rien savoir, j'avais la même erreur

Reply

Marsh Posté le 28-04-2004 à 14:29:07    

Ba deja ya les dimensions qu'il faut indiquer.
Mais aussi, il faut delcarer un ptr de ptr non ?
int** ptr ; et non int* ptr ;
enfin je crois... ca fait lgt que j'ai pas fait de C.
 

Reply

Marsh Posté le 28-04-2004 à 16:03:28    

Faudrait pas tout mélanger quand même. Le code de HelloWorld est parfaitement correct, ou alors je n'ai pas compris la question initiale.

Code :
  1. int main(void)
  2. {
  3.    int tab[6][2];
  4.    int *p;
  5.    p = &tab[2][1];
  6.    return 0;
  7. }


Si tu parlais de passage de paramètres, des exemples ont été donnés plus haut.

Reply

Marsh Posté le 28-04-2004 à 17:55:23    

Non, le passage de paramètre est bon, c'est dans ma fonction que j'avais un problème  

Code :
  1. void foo(int *tab, int d)
  2. {
  3. int *ptr;
  4. ptr = &tab[i][j];
  5. }


 
Cette derniere instruction ne passais pas au compilateur.
 
par contre celle la marche :

Code :
  1. void foo(int *tab, int d)
  2. {
  3. int *ptr;
  4. ptr = (tab + i * d + j);
  5. }


 
Et je n'ai plus d'erreur de compilation.
Mais je vois toujours pas pourquoi ptr = &tab[i][j]; ne marchais pas.

Reply

Marsh Posté le 28-04-2004 à 18:21:31    

fif_x a écrit :


Code :
  1. void foo(int *tab, int d)
  2. {
  3. int *ptr;
  4. ptr = (tab + i * d + j);
  5. }



i et j  sont des variables globales ?

Reply

Marsh Posté le 29-04-2004 à 00:42:17    

fif_x a écrit :

Non, le passage de paramètre est bon, c'est dans ma fonction que j'avais un problème  

Code :
  1. void foo(int *tab, int d)
  2. {
  3. int *ptr;
  4. ptr = &tab[i][j];
  5. }


...
Mais je vois toujours pas pourquoi ptr = &tab[i][j]; ne marchais pas.


Ce n'est pas l'affectation qui est en cause, c'est simplement que tab[i][j] ne veut rien dire, car tab n'est pas un tableau à deux dimensions ! Peut importe qu'il soit un pointeur sur le premier élément d'un tel tableau, l'information est perdue lors du passage de paramètre, dans la procédure c'est un "simple" pointeur sur un int.
 
tab[i] est totalement équivalent à *(tab + i). En l'occurrence, cette expression est de type int. tab[i][j] est donc une tentative d'indexer une expression de type int, ce qui est illégal.
 
La seule solution est donc de passer explicitement la dimension de la seconde dimension en paramètre et de faire comme tu l'as fait:

Code :
  1. ptr = (tab + i * d + j);
  2. /* ou */
  3. ptr = &tab[i * d + j];


Message édité par djdie le 29-04-2004 à 00:43:02
Reply

Marsh Posté le 29-04-2004 à 11:43:02    

Merci beaucoup de ta réponse, c'est très clair maintenant :D :jap:

Reply

Marsh Posté le 10-05-2004 à 16:22:38    

Bonjour,
 
un autre petit problème me tracasse serieusement,
J'ai un fonction du style  

Code :
  1. void fonction (char name[][MAXCARINNAME])
  2. {
  3. ...
  4. }


 
Mon main :

Code :
  1. #define MACARINNAME 20
  2. int main ()
  3. {
  4. char **Names;
  5. int nb=10,i;
  6. Names = (char**) malloc (sizeof(char*)*nb);
  7. for (i=0;i<nb;i++)
  8.  nodeNames[i] = (char*) malloc (sizeof(char)*MAXCARINNAME);
  9. fonction (Names); //PROBLEME DE COMPILATION
  10. return 0;
  11. }


gcc me dit :
AVERTISSEMENT: passage de arg 1 de « fonction » d'un type pointeur incompatible
 
Je n'arrive pas à passer Names en paramètre de la fonction, je ne trouve pas le bon format :(


Message édité par fif_x le 10-05-2004 à 16:23:37
Reply

Marsh Posté le 10-05-2004 à 16:32:40    

Ce serais déjà une bonne chose de vérifier que tes allocations mémoire se déroulent sans problème.

Code :
  1. char **Names=NULL;
  2. Names=(char**) malloc (sizeof(char*)*nb);
  3. if (Names == NULL)
  4. {
  5.   /* Message d'erreur */
  6.   exit(1);
  7. }

Tu as un tableau dont la longueur des chaines de caractères est fixe pourquoi "s'embêter" avec une deuxième dimension.

Code :
  1. char **Names=NULL;
  2. Names=(char*)calloc(sizeof(char)*nb*MAXCARINNAME);
  3. ...

Avec la fonction calloc tu auras déjà initialisé toutes tes chaines à "".
 
Pour accèder à la chaine N :

Code :
  1. strcpy(Names[N*MAXCARINNAME], "lapin" );
  2. fprintf(stdout, "%s\n", Names[N*MAXCARINNAME]);

Il faut faire attention à la longueur des chaines que tu copies, par exemple en utilisant strncpy.
Pour N entre 0 et nb-1.
MAXCARINNAME doit être égal au nombre maximal de caractère plus un (pour le fameux '\0').
 
Enfin le prototype de la fonction fonction devient :

Code :
  1. void fonction(char* name);

En espérant ne pas avoir dit trop de conneries. :D


Message édité par darkoli le 10-05-2004 à 21:26:01
Reply

Marsh Posté le 10-05-2004 à 16:41:34    

Merci beaucoup je vais essayer avec ça :)

Reply

Marsh Posté le 10-05-2004 à 16:47:45    

Sans parler de la façon d'utiliser malloc, il est logique que le compilo gueule. Names est un char**. Après initialisation, il pointera ici sur le premier élément d'un tableau de char*, et chacun de ces char* pointera sur le premier élément d'un tableau de char (après initialisation dans la boucle). Ce n'est PAS la même chose qu'un tableau à deux dimensions, même si la syntaxe utilisée pour accéder aux éléments est la même.
 
De façon imagée, le tableau à 2 dimensions est "tout plat" en mémoire. Les éléments sont rangés les uns à côtés des autres, la vision des deux dimensions est purement logique mais tu pourrais tout aussi bien le voir comme un tableau à une seule dimension; c'est simplement de l'arithmétique sur les pointeurs.
 
Par contre dans la version utilisant malloc que tu as décrit, tu construis un tableau de pointeurs qui pointent chacun sur des tableaux. Cela ressemble à un tableau à 2 dimension mais cela n'en est pas un, les éléments ne sont pas contigus en mémoire et tu as une étape d'indirection supplémentaire.
 
Donc dans le cas présent, ta fonction doit donc simplement recevoir un char** en argument.
 
En gros dans le début de ce fil, tu tentais d'enfiler un tableau à 2 dimensions dans un char** et maintenant tu tentes d'enfiler un char** dans un tableau à 2 dimensions.....

Reply

Marsh Posté le 10-05-2004 à 16:51:55    

tu fait prof de C djdie ? :)
 
Tu explique beaucoup mieux que mes anciens profs :D

Reply

Marsh Posté le 10-05-2004 à 17:08:00    


Donc il faudrai que je passe à ma fonction un tableau a 2 dimensions "plats" (si j'ai bien compris).
 
Mais si je fait comme a proposé darkoli :

Code :
  1. Names = (char**) malloc (sizeof(char)*nb*MAXCARINNAME);
  2. ...
  3. strcpy(Names[i*MAXCARINNAME], "chien" ); /*pour accéder a l'élément i */


A l'exectution, j'ai un seg fault.

Reply

Marsh Posté le 10-05-2004 à 17:11:25    

Si tu veux utiliser ta fonction telle quelle tu dois déclarer un vrai tableau à deux dimensions :

Code :
  1. char Names[10][MAXCARINNAME];

Reply

Marsh Posté le 10-05-2004 à 17:16:46    

Merci, mais le problème étant que je ne connais pas à l'avance la taille du tableau.
Donc je doit modifier le prototype de ma fonction.
 
L'autre problème c'est que dans mon programme, soit j'appelle ma fonction avec un Vrai tableau a 2 dimensions, soit je l'appelle avec un tableau a 2 dimensions alloué dynamiquement.
 
Est-ce possible de faire un prototype de fonction qui accepte les 2 types ???

Reply

Marsh Posté le 10-05-2004 à 20:27:49    

Un truc pas mal que j'ai eu en cours ce matin:
 

Code :
  1. #define HEIGHT 100
  2. #define WIDTH 100
  3. typedef long tab2d [HEIGHT][WIDTH]
  4. int fonction(tab2d var){
  5.    var[0][0] = 0;
  6.    var[1][1] = 0;
  7.    return 0;
  8. }


 
Si vous pensez qu'il y a une erreur dans le typedef, lisez votre "kernighan et Ritchie"!


Message édité par torpe23 le 10-05-2004 à 20:28:07
Reply

Marsh Posté le 10-05-2004 à 20:31:13    

je vois juste que sur un système 32bits, ton tableau fait 40ko et n'est évidemment pas souple du tout

Reply

Marsh Posté le 10-05-2004 à 21:27:02    

fif_x a écrit :

Donc il faudrai que je passe à ma fonction un tableau a 2 dimensions "plats" (si j'ai bien compris).
 
Mais si je fait comme a proposé darkoli :

Code :
  1. Names = (char**) malloc (sizeof(char)*nb*MAXCARINNAME);
  2. ...
  3. strcpy(Names[i*MAXCARINNAME], "chien" ); /*pour accéder a l'élément i */


A l'exectution, j'ai un seg fault.


J'ai copié/collé ton code et j'ai oublié d'enlever une étoile ! :D

Code :
  1. Names = (char*) malloc (sizeof(char)*nb*MAXCARINNAME);

:D

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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