|
Sujet : [c] les pointeurs |
| Musaran |
lamatrice a écrit a écrit :
je voudrais savoir par exemple : scanf("votre nom",&a)
pourquoi je doit mettre '&a' et pas 'a'
|
En C les arguments sont transmis par valeur. scanf recevrait (inutilement) la valeur de a, alors qu'il veut une adresse pour écrire.
En C++ on pourrait réecrire cette fonction pour recevoir une référence. Alors on mettrait 'a' et elle prendrait tout seule l'adresse de a (sous forme de référence).
L'intérêt du pointeur, c'est sa puissance: désigner n'importe quelle variable, existante ou même à venir, où qu'elle soit en mémoire (globale,pile,dynamique).
Je connaît ces utilisations des pointeurs/adresses: Code :
- //identité d'objet par son adresse
- if(ptr1==ptr2)... //si ptr1 et ptr2 désignent le même objet...
- //identité changeante
- ptr= test ? &a : &b ;
- *ptr=... ; //change a ou b...
- //éviter la copie de gros objet
- void f(const BigStruct* arg){ //reçoit sizeof(pointeur) octets plutôt que des tonnes...
- int tmp= BigStruct->ChampInt ; //...mais travail d'indirection supplémentaire.
- }
- //valeur de retour complexe de fonction
- void analyse(int in , BigStruct* out1 , BigStruct* out2){ //pas de const, la fonction peut modifier l'original
- scanf("bla",out1->ChampPtrChar) ; //impossible avec return
- }
- //parcours rapide de tableau
- for(int i= 0 ; i< numelem ; i++) tab[i]=... ; //par indice (normal)
- for(int* p=&tab[0] ; p<&tab[numelem] ; p++) *p =... ; //par pointeur (plus rapide)
- //allocation dynamique
- int* ptr= (int*)malloc(num*sizeof(int)) ; //allocation de num int
- ptr= (int*)realloc(ptr,2*num*sizeof(int)) ; //réallocation à 2*num int
|
lamatrice a écrit a écrit :
mais pourqoi quand on fait une affectation on utilisa pas le pointeur alors ?
a=5;
&a=5;
|
'a' tout seul, c'est juste la variable, sans plus. Après, le contexte décide: Code :
- a=... ; //écrire une valeur dedans.
- ...=a ; //lire sa valeur
- a++ ; //lire, incrémenter, et écrire
|
C'est juste les choix de base dans la syntaxe d'un langage... |
| Musaran |
lamatrice a écrit a écrit :
je voudrais savoir par exemple : scanf("votre nom",&a)
pourquoi je doit mettre '&a' et pas 'a'
|
En C les arguments sont transmis par valeur. scanf recevrait (inutilement) la valeur de a, alors qu'il veut une adresse pour écrire.
En C++ on pourrait réecrire cette fonction pour recevoir une référence. Alors on mettrait 'a' et elle prendrait tout seule l'adresse de a (sous forme de référence).
L'intérêt du pointeur, c'est sa puissance: désigner n'importe quelle variable, existante ou même à venir, où qu'elle soit en mémoire (globale,pile,dynamique).
Je connaît ces utilisations des pointeurs/adresses: Code :
- //identité d'objet par son adresse
- if(ptr1==ptr2)... //si ptr1 et ptr2 désignent le même objet...
- //identité changeante
- ptr= test ? &a : &b ;
- *ptr=... ; //change a ou b...
- //éviter la copie de gros objet
- void f(const BigStruct* arg){ //reçoit sizeof(pointeur) octets plutôt que des tonnes...
- int tmp= BigStruct->ChampInt ; //...mais travail d'indirection supplémentaire.
- }
- //valeur de retour complexe de fonction
- void analyse(int in , BigStruct* out1 , BigStruct* out2){ //pas de const, la fonction peut modifier l'original
- scanf("bla",out1->ChampPtrChar) ; //impossible avec return
- }
- //parcours rapide de tableau
- for(int i= 0 ; i< numelem ; i++) tab[i]=... ; //par indice (normal)
- for(int* p=&tab[0] ; p<&tab[numelem] ; p++) *p =... ; //par pointeur (plus rapide)
- //allocation dynamique
- int* ptr= (int*)malloc(num*sizeof(int)) ; //allocation de num int
- ptr= (int*)realloc(ptr,2*num*sizeof(int)) ; //réallocation à 2*num int
|
lamatrice a écrit a écrit :
mais pourqoi quand on fait une affectation on utilisa pas le pointeur alors ?
a=5;
&a=5;
|
'a' tout seul, c'est juste la variable, sans plus. Après, le contexte décide: Code :
- a=... ; //écrire une valeur dedans.
- ...=a ; //lire sa valeur
- a++ ; //lire, incrémenter, et écrire
|
C'est juste les choix de base dans la syntaxe d'un langage... |
| LeGreg |
lamatrice a écrit a écrit :
sinon je fait du java, et du php et j'ai jamais eu besoin d'utiliser les pointeurs (ou alors sans le savoir)
|
tous les mecanismes qui te semblent naturel en java utilisent
des pointeurs en sous-main. Java => haut niveau, C => bas niveau
notamment en java ils poussent le paradigme objet au plus loin
ce qui leur permet de faire de la prog objet tres efficace mais leur interdit tous les raccourcis faisables en C.
Le pointeur c'est l'objet de base qui dérive de l'assembleur, en haut niveau on leur donne des noms différents: reference, iterateur, tableau statique ou dynamique, chaine, etc..
Toutes les notions de la prog "elevée" sont traduisibles en C ou en assembleur. L'assembleur ne connait que les registres et les pointeurs, les goto etc.. Le C est une sorte d'assembleur évolué avec des types, des fonctions, des boucles, des macros, des mecanismes d'allocation automatiques etc..
Pour ce qui est des references en java, elles sont assez differentes des references en C++ (elles ont juste le meme nom).
En java quand tu manipules une reference, tu manipules l'objet lui-meme (pas d'arithmétique des references, pas d'operateur de deferencement), un peu comme une reference en C++. Par contre, une reference peut etre nil et peut etre reassignée dans sa durée de vie (elle fait reference a un autre objet). Un peu comme un pointeur en C/C++.
LeGreg |
| LetoII |
Bon je me lance, je vais essayer de t'expliquer (quand on connait mes capacités pédagogiques ça fait peur).
Les valeurs de tes variables sont stocké dans la mémoire de la machine. Par exemple lorsque tu déclare un long on te donne un espace méoire de 4octets où tu peux stocker la valeur de la variable.
Un pointeur est une variable qui contient l'adresse d'une autre variable, c'est à dire l'endroit de la méoire où se trouve la valeur de ta variable.
Prenons un exemple:
Code :
- #include <stdio.h>
- void exempleProc1(int i, int j)
- {
- i += j;
- }
- void exempleProc2(int *i, int *j)
- {
- *i += *j;
- }
- int main()
- {
- int a,b;
- a = 1;
- b = 2;
- exempleProc1(a,b);
- printf("%d,%d",a,b);
- /*affiche 1,2*/
- exempleProc2(&a,&b);
- printf("%d,%d",a,b);
- /*affiche 3,2*/
- return 0;
- }
|
Dans le cas de printf on ne fait que lui passer des valeur à afficher donc elle n'as pas besoin d'avoir les adrese des variables contenant ces valeurs.
Pour scanf c'est différent, elle doit modifier tes variables, pour celà tu lui passe leurs adresses pour qu'elle aille modifier les valeurs stockées. |