probleme pour permutter 2 entiers par adresse...

probleme pour permutter 2 entiers par adresse... - C - Programmation

Marsh Posté le 08-08-2003 à 14:41:31    

:hello:  ,J'ai fait le petit test d'échange de valeurs suivant :
 
void swap(int *a,int *b);
 
void main()
{
int a,b;
int *aa=&a;
int *bb=&b;
a=3,b=5;
printf("contenu de a: %d ,contenu de b: %d\n",a,b);
swap(aa,bb);//permutation...
printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
}
 
 
void swap(int *x,int *y)//passage des parametres par adresse
{
 
int *temp;
printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",x,y,temp);
 
//permutation des adresses ou pointe les pointeurs
temp=x;
x=y;
y=temp;
 
printf("adresse de x: %x ,adresse de y: %x\n",x,y);
printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
}
 
 
Dans la fonction swap() tout est bien permuté aussi bien les adresses que les contenus.Par contre de retour dans le main, "a" et "b" ne sont pas permuttés ! Mais pourquoi alors que j'ai transmis a et b par leurs adresses quand j'ai appelé la fonction swap().Je sais que si je transforme la fonction swap() comme ci apres  
 
*temp=*x;
*x=*y;
*y=*temp;
 
ça fonctionne mais je veux échanger par adresse dans swap() et non par contenu de pointeur.Comment dois je m'y prendre ??? j'ai oublié un détail peut etre ??
 
D'avance merci pour votre aide  :hello:  

Reply

Marsh Posté le 08-08-2003 à 14:41:31   

Reply

Marsh Posté le 08-08-2003 à 14:45:03    

neo9205 a écrit :

:hello:  ,J'ai fait le petit test d'échange de valeurs suivant :
 
void swap(int *a,int *b);
 
void main()
{
int a,b;
int *aa=&a;
int *bb=&b;
a=3,b=5;
printf("contenu de a: %d ,contenu de b: %d\n",a,b);
swap(aa,bb);//permutation...
printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
}
 
 
void swap(int *x,int *y)//passage des parametres par adresse
{
 
int *temp;
printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",x,y,temp);
 
//permutation des adresses ou pointe les pointeurs
temp=x;
x=y;
y=temp;
 
printf("adresse de x: %x ,adresse de y: %x\n",x,y);
printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
}
 
 
Dans la fonction swap() tout est bien permuté aussi bien les adresses que les contenus.Par contre de retour dans le main, "a" et "b" ne sont pas permuttés ! Mais pourquoi alors que j'ai transmis a et b par leurs adresses quand j'ai appelé la fonction swap().Je sais que si je transforme la fonction swap() comme ci apres  
 
*temp=*x;
*x=*y;
*y=*temp;
 
ça fonctionne mais je veux échanger par adresse dans swap() et non par contenu de pointeur.Comment dois je m'y prendre ??? j'ai oublié un détail peut etre ??
 
D'avance merci pour votre aide  :hello:  
 


 
 :heink:  

Code :
  1. void swap(int **a,int **b);
  2. void main()
  3. {
  4. int a,b;
  5. int *aa=&a;
  6. int *bb=&b;
  7. a=3,b=5;
  8. printf("contenu de a: %d ,contenu de b: %d\n",a,b);
  9. swap(aa,bb);//permutation...
  10. printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
  11. }
  12. void swap(int **x,int **y)//passage des parametres par adresse
  13. {
  14. int *temp;
  15. printf("contenu de x: %d ,contenu de y: %d\n",**x,**y);
  16. printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",*x,*y,temp);
  17. //permutation des adresses ou pointe les pointeurs
  18. temp=*x;
  19. *x=*y;
  20. *y=*temp;
  21. printf("adresse de x: %x ,adresse de y: %x\n",*x,*y);
  22. printf("contenu de x: %d ,contenu de y: %d\n",**x,**y);
  23. }

Reply

Marsh Posté le 08-08-2003 à 15:06:45    

LetoII a écrit :


 
 :heink:  

Code :
  1. void swap(int **a,int **b);
  2. void main()
  3. {
  4. int a,b;
  5. int *aa=&a;
  6. int *bb=&b;
  7. a=3,b=5;
  8. printf("contenu de a: %d ,contenu de b: %d\n",a,b);
  9. swap(aa,bb);//permutation...
  10. printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
  11. }
  12. void swap(int **x,int **y)//passage des parametres par adresse
  13. {
  14. int *temp;
  15. printf("contenu de x: %d ,contenu de y: %d\n",**x,**y);
  16. printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",*x,*y,temp);
  17. //permutation des adresses ou pointe les pointeurs
  18. temp=*x;
  19. *x=*y;
  20. *y=*temp;
  21. printf("adresse de x: %x ,adresse de y: %x\n",*x,*y);
  22. printf("contenu de x: %d ,contenu de y: %d\n",**x,**y);
  23. }




 
tu n'as pas compris ce que je voulais vraiment...En fait je veux que la fonction swap()contienne ceci :
temp=x;
x=y;
y=temp;
 
//Et qu'elle fonctionne bien sur vis à vis du main()->permutation correcte
 
Et pas cela:
temp=*x;
*x=*y;
*y=*temp;
 
 

Reply

Marsh Posté le 08-08-2003 à 15:12:56    

Faut dire ct pas clair
 

Code :
  1. void swap(int *a,int *b);
  2. void main()
  3. {
  4. int a,b;
  5. int *aa=&a;
  6. int *bb=&b;
  7. a=3,b=5;
  8. printf("contenu de a: %d ,contenu de b: %d\n",a,b);
  9. swap(aa,bb);//permutation...  
  10. printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
  11. }
  12. void swap(int *x,int *y)//passage des parametres par adresse  
  13. {
  14. int temp;
  15. printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
  16. printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",x,y,temp);
  17. //permutation des adresses ou pointe les pointeurs  
  18. temp=*x;
  19. *x=*y;
  20. *y=temp;
  21. printf("adresse de x: %x ,adresse de y: %x\n",x,y);
  22. printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
  23. }


Message édité par LetoII le 08-08-2003 à 15:13:31

---------------
Le Tyran
Reply

Marsh Posté le 08-08-2003 à 15:57:14    

LetoII a écrit :

Faut dire ct pas clair
 

Code :
  1. void swap(int *a,int *b);
  2. void main()
  3. {
  4. int a,b;
  5. int *aa=&a;
  6. int *bb=&b;
  7. a=3,b=5;
  8. printf("contenu de a: %d ,contenu de b: %d\n",a,b);
  9. swap(aa,bb);//permutation...  
  10. printf("contenu de a apres permutation: %d\t,contenu de b apres permutation: %d\n",*aa,*bb);
  11. }
  12. void swap(int *x,int *y)//passage des parametres par adresse  
  13. {
  14. int temp;
  15. printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
  16. printf("adresse de x: %x ,adresse de y: %x,adresse de temp: %x\n",x,y,temp);
  17. //permutation des adresses ou pointe les pointeurs  
  18. temp=*x;
  19. *x=*y;
  20. *y=temp;
  21. printf("adresse de x: %x ,adresse de y: %x\n",x,y);
  22. printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
  23. }




 
Y a plus d'étoile à temp mais y en a encore à x et y ce que je ne veux pas.

Reply

Marsh Posté le 08-08-2003 à 16:05:30    

:heink: Tu peux pas faire autrement hein


---------------
Le Tyran
Reply

Marsh Posté le 08-08-2003 à 16:21:25    

LetoII a écrit :

:heink: Tu peux pas faire autrement hein  

les pointeurs c'est pas sal!

Reply

Marsh Posté le 08-08-2003 à 17:48:54    

Taz a écrit :

les pointeurs c'est pas sal!


 
J'ai jamais dit le contraire mais soit il s'exprime mal soit il a déjà la solution  [:spamafote]


---------------
Le Tyran
Reply

Marsh Posté le 08-08-2003 à 19:37:17    

LetoII a écrit :


 
J'ai jamais dit le contraire mais soit il s'exprime mal soit il a déjà la solution  [:spamafote]  


 
visiblement, ce qu'il veut, c'est un mécanisme comme les références en C++, mais c'est pas dispo en C, désolé ...
 
Edit : A la limite, ca peut se faire via une macro, dans ce cas .... (pas taper, Taz ! :ange:)


Message édité par theshockwave le 08-08-2003 à 19:56:38

---------------
last.fm
Reply

Marsh Posté le 08-08-2003 à 21:35:49    

theShOcKwAvE a écrit :


 
visiblement, ce qu'il veut, c'est un mécanisme comme les références en C++, mais c'est pas dispo en C, désolé ...
 
Edit : A la limite, ca peut se faire via une macro, dans ce cas .... (pas taper, Taz ! :ange:)


 
Oui apparement c'est pas possible comme je veux.par contre en C++ ça marchera ce que je veux il semble.

Reply

Marsh Posté le 08-08-2003 à 21:35:49   

Reply

Marsh Posté le 08-08-2003 à 21:37:37    

en C t'as pas le choix.
Les pointeurs c'est plus propre que les références de C++. Pk ?
Tout simplement parce que çà oblige a réfléchir a ce qu'on fait et a comprendre comment la machine fonctionne.
C'est donc une très bonne chose.
 
Car à force de les mépriser on arrive avec énormément de personnes qui se disent programmeur, et qui ne maitrisent pas cette notion pourtant essentielle de la prog.

Reply

Marsh Posté le 08-08-2003 à 21:39:54    

Lalorette a écrit :

en C t'as pas le choix.
Les pointeurs c'est plus propre que les références de C++. Pk ?
Tout simplement parce que çà oblige a réfléchir a ce qu'on fait et a comprendre comment la machine fonctionne.
C'est donc une très bonne chose.
 
Car à force de les mépriser on arrive avec énormément de personnes qui se disent programmeur, et qui ne maitrisent pas cette notion pourtant essentielle de la prog.

je vois pas en quoi c'est plus propre...

Reply

Marsh Posté le 09-08-2003 à 00:06:06    

En C, TOUS les arguments de fonctions sont passés par valeur, même si ce sont des arguments de type pointeur.
 
Ainsi, quand tu écris:
 
 void swap(int *x,int *y) // passage des parametres par adresse
 
en fait ton commentaire est légèrement erroné, car la fonction swap(...) ne fait que recevoir des VALEURS qui se trouvent être de type int* (pointeurs d'entier).
 
Que fait ta fonction swap()? Elle s'alloue LOCALEMENT -- j'insiste sur ce terme! -- deux variables x et y de type int*, lesquelles variables reçoivent des valeurs fournies par l'appelant.
 
Pour simplifier, disons que dans main() tu as:
 
 int  A;  // déclare et alloue A de type int
 int  B;  // déclare et alloue B de type int
 
 int* pA; // déclare et alloue pA de type int*
 int* pB; // déclare et alloue pB de type int*
 
 pA = &A; // charge dans pA l'adr de A
 pB = &B; // charge dans pB l'adr de B
 
[je garderai ces notations par la suite]
 
Lorsque tu fais swap(pA, pB), il se passe implicitement et localement, compte tenu du prototype de la fonction:
 
 int* x; // déclare/alloue localement x de type int*
 int* y; // déclare/alloue localement y de type int*
 x = pA; // charge dans x la VALEUR de pA
         // (en l'occurrence l'adr de A = &A)
 y = pB; // charge dans y la VALEUR de pB
         // (en l'occurrence l'adr de B = &B)
 
A partir de là, toutes les opérations que tu vas faire DIRECTEMENT sur x ou sur y, du genre:
 
<<
...
x=y;
y=temp;
...
>>
 
se bornent à permuter, non pas des "adresses" au sens où tu l'entends, mais simplement des valeurs temporaires de variables locales.
 
A l'issue de ce bout de code, compte tenu du contexte, x contient effectivement l'adresse de B et y l'adr de A (puisque x et y ont échangé leurs valeurs, initialisées sur pA et pB), MAIS aucune des variables A, B, pA, pB n'ont changé de valeur!
 
Donc, il ne faut pas s'étonner si, revenant dans le main(), tout est comme avant.
 
Quand tu écris que tout se passe bien dans le swap, c'est d'ailleurs un trompe-l'oeil, vu ton code de test:
 
<<
printf("adresse de x: %x ,adresse de y: %x\n",x,y);
printf("contenu de x: %d ,contenu de y: %d\n",*x,*y);
>>
 
Ce test est inexact car:
- l'ADRESSE d'une variable X n'est pas "X" mais "&X"
- le CONTENU d'une variable X n'est pas "*X" mais "X" (!)
- l'écriture "*X" représente le contenu (évalué selon le typage du pointeur) situé à l'adresse contenue dans X
 
Ta question initiale était:
 
<< De retour dans le main, "a" et "b" ne sont pas permutés! Mais pourquoi alors que j'ai transmis a et b par leurs adresses >>
 
La réponse est que tu n'as pas TRANSMIS a et b par leurs adresses, tu as chargé dans x et y locales des valeurs qui se trouvent être les adresses de a et b ...mais sans jamais manipuler le contenu de ces adresses.
 
La seule manière de le faire était évidemment de passer par *x et *y. Je ne comprends pas ta "contrainte" t'imposant d'<<échanger par adresse dans swap() et non par contenu de pointeur>>. Au demeurant, cette formule n'est pas claire du tout. Le mécanisme des pointeurs te permet de modifier dans une fonction la valeur d'une variable qui lui est externe mais dont elle connaît l'adresse, pourquoi voudrais-tu te priver de cette fonctionnalité intrinsèque du C?
 
Le C++ a introduit le passage d'argument par référence, càd réellement "par adresse" au sens où tu l'entends. C'est essentiellement une amélioration syntaxique, puisque ça permet de prototyper swap(int& x, int& b) et d'appeler swap(A,B) pour manipuler -- dans swap! -- directement les variables-arguments (et non des recopies de leur valeur).
 
Mais, dans tous les cas de figure, il est peut-être utile de rappeler qu'étant donné une variable X de type qcq, l'adresse de X (&X) n'est pas accessible EN ECRITURE. Tu peux faire en sorte qu'un pointeur pX pointe sur &Y au lieu de pointer sur &X, tu peux modifier la valeur de X indirectement via un pointeur (opérateur *), mais aucun code ne te permet de "réadresser" X. Donc, si ton objectif était d'échanger les adresses de A et de B... c'est voué à l'échec.
 
Pour aller + loin, il ne serait pas superflu que tu nous précises exactement le cahier des charges de ta fonction swap(). Au fond, quelles valeurs doit-elle échanger:
1 - celles de A et B seulement ?
2 - celles de pA et pB seulement ?
3 - celles de A et B ET de pA et pB ?
 
Dans les cas 2 et 3, il sera nécessaire de fournir à swap les adresses de pA et pB, ce qui force à prototyper:
 
 swap(int** X, int** Y)
 
et à appeler la fonction avec un swap(&pA, &pB)
 
Dans le cas 3, le code pourrait être du genre:
 
 void swap(int** X, int** Y)
 // Contexte extérieur:
 //  int A ; int B ; int* pA=&A ; int* pB=&B;
 // Objectifs:
 //  échanger les val de A et B  ET  les val de pA et pB
 // Situation initiale implicite:
 //  X = &pA  |  *X = pA  -  **X = *pA = A
 //  Y = &pB  |  *Y = pB  -  **Y = *pB = B
 {
 int  tmp1;  // var tempo pour swapper des INT
 int* tmp2;  // var tempo pour swapper des INT*
 
 // échanger les valeurs de A et B
 tmp1 = **X;  // sauvegarder la valeur de A
 **X = **Y;   // charger dans A la valeur de B
 **Y = tmp1;  // charger dans B la valeur sauvergardée
 
 // A ce stade, les var externes A et B
 // ont leurs valeurs permutées, mais on
 // a encore: pA=&A et pB=&B
 // et, bien sûr, X=&pA et Y=&pB
 
 // échanger les valeurs de pA et pB
 tmp2 = *X;  // sauvegarder la valeur de pA(=&A)
 *X = *Y;    // charger dans pA la valeur de pB(=&B)
 *Y = tmp2;  // charger dans pB la valeur sauvergardée
 
 // A ce stade, d'une part les var externes A et B
 // ont leurs valeurs permutées, d'autre part
 // pA=&B et pB=&A (v. commentaire infra)
 
 }
 
Observons pour en finir que cette double permutation a pour conséquence que:
- pA pointe sur B qui a pris la valeur initiale de A
- pB pointe sur A qui a pris la valeur initiale de B
 
Donc, si on note a la valeur init. de A et b la valeur init. de B avant l'appel de swap, on a en sortie:
 
 A = b  , B = a
 pA = &B  , pB = &A
 *pA = a  , *pB = b (!)
 
Ce n'était probablement pas l'objectif poursuivi, mais je crois que l'exercice avait valeur pédagogique... Non?


Message édité par ACut le 09-08-2003 à 00:22:10
Reply

Marsh Posté le 09-08-2003 à 00:15:42    

ben fais un edit

Reply

Marsh Posté le 09-08-2003 à 00:27:28    

Merci, Taz. J'avais pas encore trop le réflexe...

Reply

Marsh Posté le 09-08-2003 à 13:02:50    

ACut a écrit :

En C, TOUS les arguments de fonctions sont passés par valeur, même si ce sont des arguments de type pointeur.
 
Ainsi, quand tu écris...
 


Extra ta réponse, c'est exactement ce que je cherchais à comprendre.Je voulais vraiment exploiter à fond les pointeurs et les comprendre dans les moindres détails et là ça va beaucoup mieux avec ton explication.
 
En fait, je voulais tenter d'échanger les valeurs de a et b via leur adresses respectives.De cette manière, a aurait la valeur de b et b la valeur de a tout ceci via la fonction swap().
En tout cas merci pour ton explication  :hello:


Message édité par neo9205 le 09-08-2003 à 13:47:11
Reply

Marsh Posté le 09-08-2003 à 13:07:53    

meme remarque pour toi neo: pas la peine de citer 15 pages surtout si la citation ne te sers à rien

Reply

Marsh Posté le 10-08-2003 à 14:35:29    

De rien, j'ai pris plaisir à y réfléchir.

Reply

Marsh Posté le 10-08-2003 à 14:51:34    

ACut a écrit :


 A = b  , B = a
 pA = &B  , pB = &A
 *pA = a  , *pB = b (!)


 
Ah non je me suis emballé trop vite face à ta réponse...En fait, tu as une petite erreur :
 
*pA=b puisque pA pointe sur b (pA=&B)
*pB=a puisque pB pointe sur a (pB=&A)

Reply

Marsh Posté le 10-08-2003 à 17:18:58    

Non, pas d'accord avec toi, je ne vois pas mon erreur. Tu écris:
 
<<
*pA=b puisque pA pointe sur b (pA=&B)
*pB=a puisque pB pointe sur a (pB=&A)
>>
 
Or:
 
pA = &B   // pA = adresse de la variable "B"
 
  donc
 
*pA = (valeur de la variable "B" )
      // et non pas "pA pointe sur b"
 
  or
 
B vaut a  (à ce stade du process, puisque permutation avant)
 
 donc :
 
*pA = a  // ce qui ne veut pas dire:
         // *pA = valeur de "A" actuelle
         // mais:
         // *pA = valeur initiale de "A"
 
 


Message édité par ACut le 10-08-2003 à 17:26:34
Reply

Marsh Posté le 10-08-2003 à 17:19:48    

ACut a écrit :

Je suis banni du forum (TT), donc je pense que je ne pourrais pas te répondre, mais je crois que tu te plantes...

:heink:

Reply

Marsh Posté le 10-08-2003 à 17:34:09    

Ouah!
 
Je savais pas qu'être censuré sur une branche laissait la possibilité de s'exprimer sur les autres branches!
 
Taz, tu vas pas me zigouiller toi aussi? Ton camarade krapaud m'a adressé le mail suivant:
 
<<comportement infantile, niaiserie à propos du p2p>>
 
qui me vaut d'être évincé de Software&Réseau
 
Je n'ai donc pas pu répondre aux attaques de ces intellectuels. Dommage, mes arguments étaient pondérés je crois...
 
Bref, fin de digression

Reply

Marsh Posté le 14-08-2003 à 09:33:12    

... tu vas couiner longtemps comme ça?

Reply

Marsh Posté le 14-08-2003 à 09:45:49    

Retourne dans ton Reich, craporal. Tu vois pas qu'ici les gens ont un cerveau?


---------------
NOUVEAU! Le guide de l'édition en version ebook : http://marcautret.free.fr/autret/150q-ebook/
Reply

Marsh Posté le 14-08-2003 à 09:47:33    

halte au feu. ici, c'est moi qui commande.

Reply

Marsh Posté le 14-08-2003 à 09:54:26    

ACut a écrit :

Retourne dans ton Reich, craporal. Tu vois pas qu'ici les gens ont un cerveau?


 
heu t'es sûr que tu veux continuer à pouvoir poster ici ?


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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