Vous n'êtes pas identifié(e).
L'icône rouge permet de télécharger chaque page du wiki visitée au format PDF et la grise au format ODT →
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente Prochaine révision Les deux révisions suivantes | ||
utilisateurs:hypathie:tutos:memo-c [19/08/2014 07:25] Hypathie [Variables] |
utilisateurs:hypathie:tutos:memo-c [19/08/2014 10:16] Hypathie [Les pointeurs] |
||
---|---|---|---|
Ligne 91: | Ligne 91: | ||
<code>gcc -o nom-exécutable nom fichier-à-compiler</code> | <code>gcc -o nom-exécutable nom fichier-à-compiler</code> | ||
- | <code user>gcc main.x main.c</code> | + | <code user>gcc -o main.x main.c</code> |
<code user>ls</code> | <code user>ls</code> | ||
<code> | <code> | ||
Ligne 1237: | Ligne 1237: | ||
=====Les pointeurs ==== | =====Les pointeurs ==== | ||
- | ===Déclarer un pointeur === | + | ====Définitions==== |
+ | |||
+ | __**Un pointeur est un objet Lvalue**__((left value : tout objet pouvant être placé à gauche d'un opérateur d'affectation.)) dont la valeur est égale à l'adresse d'un autre objet.\\ On déclare un pointeur par l'instruction : **''type *nom-du-pointeur;''**, où "type" est le type de l'objet pointé.\\ | ||
+ | |||
+ | Cette déclaration déclare un **identificateur**, nom-du-pointeur, associé à un objet dont la **valeur est l'adresse d'un autre objet de type "type"**.\\ | ||
+ | |||
+ | L'**identificateur nom-du-pointeur** est donc en quelque sorte un **identificateur d'adresse**. Comme pour n'importe quelle Lvalue\\ | ||
+ | |||
+ | __Une **Lvalue** est caractérisée par__ : | ||
+ | |||
+ | * **son adresse**, c'est-à-dire l'adresse-mémoire à partir de laquelle l'objet est stocké ; | ||
+ | * **sa valeur**, c'est-à-dire ce qui est stocké à cette adresse; sa valeur est modifiable. | ||
+ | |||
+ | Si le compilateur a placé la variable **''i''** à l'adresse 4831836000 en mémoire, et la variable **''j''** à l'adresse 4831836004, on a : | ||
+ | |||
+ | ^objet ^adresse ^valeur ^ | ||
+ | |i | 4831836000 | 3 | | ||
+ | |j | 4831836004 | 3 | | ||
+ | |||
+ | * Deux variables différentes ont des adresses différentes.\\ | ||
+ | L'affectation **''i = j;''** n'opère que sur les **valeurs** des variables.\\ | ||
+ | Les variables i et j étant de type **''int''**, elles sont stockées sur 4 octets.\\ | ||
+ | Ainsi la valeur de i est stockée sur les octets d'adresse 4831836000 à 4831836003.\\ | ||
+ | |||
+ | * Pour **un pointeur sur un objet de type char**, la valeur donne l'adresse de l'octet où cet objet est stocké. | ||
+ | |||
+ | * **L'opérateur ''&''** permet d'accéder à l'adresse d'une variable.\\ | ||
+ | Toutefois **''&i''** n'est pas une "Lvalue" mais une "constante" : on ne peut pas faire figurer **''&i''** à gauche d'un opérateur d'affectation.\\ | ||
+ | Pour pouvoir manipuler des adresses, on doit donc recourir un nouveau type d'objets, les **pointeurs**. | ||
+ | * **L'opérateur unaire d'indirection ''*''** permet d'accéder directement __à la valeur de l'objet pointé__.\\ | ||
+ | Ainsi, si **''p''** est un pointeur vers un entier **''i''**, **''*p''** désigne la **''valeur de i''**. | ||
+ | |||
+ | ===Exemple=== | ||
<code c> | <code c> | ||
- | int *p; | + | #include<stdio.h> |
- | p=&a | + | main() |
+ | { | ||
+ | int i = 3; | ||
+ | int *p; | ||
+ | |||
+ | p = &i; | ||
+ | printf("*p = %d \n",*p); | ||
+ | } | ||
+ | </code> | ||
+ | <code> | ||
+ | *p = 3 | ||
</code> | </code> | ||
- | <note tip> | + | On se trouve dans la configuration : |
- | * **''<nowiki>*</nowiki>''** : signifie pointeur | + | |
- | * **''<nowiki>*p</nowiki>''** : pointeur (*) est déclaré sous le nom de "p" | + | |
- | * **''<nowiki>int *p</nowiki>''** : le pointeur "p" pointe vers un entier (int) | + | |
- | * **''<nowiki>p=&a</nowiki>''** : le pointeur "p" a l'adresse (&) de "a" | + | |
- | * **''FONCTION1(type*n) ...FONCTION2(&m)''** :\\ signifie que la variable "n", de la FONCTION1, prend la valeur la variable "m", de la FONCTION2 | + | |
- | </note> | + | ^objet ^adresse ^valeur ^ |
+ | |i | 4831836000 | 3 | | ||
+ | |p | 4831836004 | 4831836000 | | ||
+ | |*p | 4831836000 | 3 | | ||
- | ===Exemples === | + | Pour aller plus loin, voir [[https://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html]] |
+ | |||
+ | ====Créer une fonction "inverser" avec des pointeurs ==== | ||
<code c> | <code c> | ||
Ligne 1305: | Ligne 1347: | ||
</note> | </note> | ||
+ | ====tableau bis ==== | ||
+ | Un tableau est pointeur qui pointe vers le premier élément du tableau. | ||
+ | ===tableau int=== | ||
+ | <code c> | ||
+ | #include<stdio.h> | ||
+ | int main(void){ | ||
+ | int tab[10]; | ||
+ | tab[0]=10; | ||
+ | tab[1]=20; | ||
+ | tab[2]=30; | ||
+ | printf("%d\t%d\t%d\n",tab[0],tab[1],tab[2]); | ||
+ | printf("%d\n",*(tab)); | ||
+ | printf("%d\n",*(tab+1)); | ||
+ | printf("%d\n",*(tab+2)); | ||
+ | printf("%d\n",*(tab+3)); | ||
+ | printf("\n"); | ||
+ | *(tab+2)=60; | ||
+ | printf("%d\n",tab[2]); | ||
+ | printf("\n"); | ||
+ | tab[2]=55; | ||
+ | printf("%d\n",*(tab+2)); | ||
+ | printf("%d\n",tab[2]); | ||
+ | } | ||
+ | </code> | ||
+ | <code> | ||
+ | 10 20 30 | ||
+ | 10 | ||
+ | 20 | ||
+ | 30 | ||
+ | 0 | ||
+ | 60 | ||
+ | 55 | ||
+ | |||
+ | </code> | ||
+ | |||
+ | >**''*tab''** : ce qui est pointé par tab | ||
+ | >**''tab[0]''** : premier élément du tableau | ||
+ | >**'' *(tab+2)''** et **''tab[2]''** ont la même valeur, on peut modifier la valeur par le biais de **''tab[2]''** ou de **'' *(tab+2)''**. | ||
+ | >**''*(tab+1)''** : premier élément du tableau + 4 octets (entier sur 4 octets), c'est-à-dire valeur du deuxième élément du tableau (le premier est ''tab[0]'' ou ''*(tab+0)'' ) | ||
+ | >**''*(tab+2)''** : premier élément du tableau + 8 octets, c'est-à-dire valeur du troisième élément du tableau. | ||
+ | > etc. | ||
+ | ===tableau char=== | ||
+ | |||
+ | <code c> | ||
+ | #include<stdio.h> | ||
+ | int main(void){ | ||
+ | char tab[27]; | ||
+ | tab[0]='a'; | ||
+ | tab[1]='b'; | ||
+ | tab[3]='c'; | ||
+ | tab[4]='d'; | ||
+ | tab[5]='e'; | ||
+ | tab[6]='f'; | ||
+ | tab[7]='g'; | ||
+ | tab[8]='h'; | ||
+ | tab[9]='i'; | ||
+ | tab[10]='j'; | ||
+ | tab[11]='k'; | ||
+ | tab[12]='l'; | ||
+ | tab[13]='m'; | ||
+ | tab[14]='n'; | ||
+ | tab[15]='o'; | ||
+ | tab[16]='p'; | ||
+ | tab[17]='q'; | ||
+ | tab[18]='r'; | ||
+ | tab[19]='s'; | ||
+ | tab[20]='t'; | ||
+ | tab[21]='u'; | ||
+ | tab[22]='v'; | ||
+ | tab[23]='w'; | ||
+ | tab[24]='x'; | ||
+ | tab[26]='y'; | ||
+ | tab[27]='z'; | ||
+ | printf("%c\t %c\t %c\t %c\t %c\t %c\n",tab[0],tab[5],tab[9],tab[15],tab[21],tab[26]); | ||
+ | *(tab+0)='A'; | ||
+ | tab[5]='E'; | ||
+ | printf("%c\t %c\n",tab[0],*(tab+5)); | ||
+ | } | ||
+ | </code> | ||
+ | <code> | ||
+ | a e i o u y | ||
+ | A E | ||
+ | </code> | ||
+ | |||
+ | * Idem en mieux (pour mémoire dure) : | ||
+ | <code c> | ||
+ | #include<stdio.h> | ||
+ | int main(void){ | ||
+ | char tab[27]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; | ||
+ | printf("%c\t %c\t %c\t %c\t %c\t %c\n",tab[0],tab[5],tab[9],tab[15],tab[21],tab[26]); | ||
+ | *(tab+0)='A'; | ||
+ | tab[5]='E'; | ||
+ | printf("%c\t %c\n",tab[0],*(tab+5)); | ||
+ | } | ||
+ | </code> |