Aller au contenu

Cours #3 - Pointeurs, tableaux et chaines de caractères


AlexMog
 Share

Recommended Posts

Bonjour à tous,
Aujourd'hui, nous allons apprendre à assimiler la notion de pointeurs, de tableaux et de chaines de caractères.

Je vais tenter de vous expliquer le fonctionnement d'un pointeur par des exemples variés. Pourquoi?
Eh bien, par mon expérience, la notion de pointeurs est une chose qui m'a fait fuir à l'époque ou j'avais commencé le C, mais uniquement à cause de la difficulté à comprendre le principe. Je vais donc essayer d'être le plus claire possible.
Ce qui nous amène donc à la première partie:

I- Un pointeur, Kesako?
Alors, un pointeur, ça n'a rien de bien méchant. C'est une variable, comme les autres, qui permet de contenir une adresse (généralement, l'adresse d'une autre variable, on parle bien sur des adresses MEMOIRE)
Pour mieux comprendre, voyons ce qui se passe lors de la création d'une variable.
Lorsque vous créez une variable, de type char par exemple, lors de l'exécution de votre programme, votre programme va prévoir une place en mémoire pour contenir votre variable. Cette place va être reconnue grâce à une adresse, qui peut être contenue dans un pointeur.
Il faut se dire qu'un type char permet de contenir 8 bit de données (soit en valeur maximale
numérique de 255), et qu'un type int peut contenir jusqu'à 32 bits de données (en fonction de la
version de votre machine, sur un 64 bits, il aura 64 bits).
(Vous comprenez mieux pourquoi les typages ont été inventés, et pourquoi il est important de bien
choisir son type de variable).
Donc, lorsque vous lancer votre programme, la machine va allouer un endroit dans la mémoire et lui donner une adresse qui permettera de dire "ICI, la variable X est stockée".
Un pointeur va donc contenir l'adresse d'une variable, pour pouvoir modifier le contenu de la dite variable (vous verrez que la gestion d'adresses est importante lorsqu'on va jouer avec les tableaux).
Donc, comprenons par l'exemple. Je vais créer un programme, qui définit une variable de type char a, et une autre variable b, qui sera un pointeur sur la variable a.

void my_putchar(char c) {
 write(1, &c, 1); // Voir cours 1 pour cette fonction
}
int main(void) {
 char a; // Déclaration de la variable a
 char *b; // Déclaration du pointeur B, le * permet de définir au PC qu'il s'agit d'un pointeur.
 a = 'b'; // On assigne une valeur à la variable a.
 my_putchar(a); // ceci affichera: b
 b = &a; // On assigne à b l'adresse de a, le signe & permet de définir que l'on récupère l'adresse de a dans b
*b = 'c' // On assigne enfin à l'adresse choisie la valeur 'c'. le * définit que l'on modifie le contenu de l'adresse mémoire et NON PAS l'adresse en elle même!
 my_putchar(*; // On affiche la valeur de b
 my_putchar(a); // On affiche la valeur de a, et on se rends bien compte qu'elle a changée!
 return (0);
}

Vous savez à présent ce qu'est un pointeur et comment l'utiliser.

II- Les tableaux statiques: WTF is that shiet?
Pour faire simple, un tableau, c'est un "regroupement" de variables du même typage, dont les adresses sont suivies les unes après les autres.
Prenons pour exemple une "mémoire" vide:
|00| |01| |10| |11|
| | | | | | | |
Pour l'instant elle ne contient aucune données, déclarons alors notre tableau de char, et ayant 3 de grandeur
|00| |01| |10| |11|
|yy| |xx| |xx| | |
Dans notre cas, yy corresponds au début du tableau, et les xx représentent les valeurs contenues dans ce tableau. Comme vous pouvez le constater, les valeurs se suivent.
Donc, en théorie, si on a un pointeur qui pointe sur l'adresse de yy, on peut parcourir notre tableau.
On peut donc affirmer qu'un tableau n'est rien d'autre qu'un pointeur qui pointe sur la première valeur de celui-ci.
Pour mieux comprendre, imaginons que je déclare un tableau comme ceci:

char tab[3];

Lorsque je vais tenter d'accéder à la première valeur, je vais donc faire ceci:

tab[0];

Eh bien, vous pouvez aussi y accéder en utilisant directement l'adresse de ce tableau

*(tab + (0 * sizeof(char));

Je viens donc de vous démontrer que le contenu des [] n'est que le multiplicateur d'accès à la "case" du tableau. Il suffit d'ajouter à notre pointeur un multiple de la taille de son typage pour accéder à la valeur suivante!
La démonstration est faite: Un tableau est un pointeur. Mais attention! Un tableau est un pointeur, mais un pointeur n'est PAS toujours un tableau.

III- Les chaines de caractères: Tu voulais pas plutôt dire chaines de vélo?!
Nous allons essayer de comprendre ensemble comment fonctionne une chaine de caractères. Et il n'y a pas de meilleurs langages que le C pour vous expliquer le principe même d'une chaine de caractères.
Nous avions déjà vu dans le cours #1 qu'une chaine de caractères n'était rien d'autre qu'un tableau contenant, dans chacune de ses cases, un caractère.
Par exemple:

char tab[6];
tab[0] = 'c';
tab[1] = 'o';
tab[2] = 'u';
tab[3] = 'c';
tab[4] = 'o';
tab[5] = 'u';

le tableau que je viens de déclarer contiendra "coucou".
La déclaration ci-dessus est fausse. Le problème étant que lorsqu'on va vouloir afficher cette chaine, on ne saura JAMAIS lorsqu'elle va s'arrêter, et donc, on risquera de provoquer ce qu'on appelle un "segfault" ou "segmentation fault" (ce qui corresponds à une tentative d'accès mémoire qui n'appartiens pas à votre logiciel).
Il est donc primordial de dire à votre programme quand est-ce que cette chaine s'arrête.
C'est en faite très simple à mettre en place, il suffit de rajouter, dans la dernière case, le caractère '\0' (qui signifie 0 en valeur numérique).
Par exemple:

char tab[7];
tab[0] = 'c';
tab[1] = 'o';
tab[2] = 'u';
tab[3] = 'c';
tab[4] = 'o';
tab[5] = 'u';
tab[6] = '\0';

Nous venons de définir une fin à notre tableau. Il existe d'autres façon de déclarer un tableau de caractères, comme ceci:

char tab[] = "coucou";

Vous savez à présent comment fonctionne une chaine de caractères.
Allons encore plus loin à présent. Je vous ai démontré toute à l'heure qu'un tableau était un pointeur.
Je peux donc affirmer que je peut utiliser l'adresse principale d'un tableau pour déclarer une chaine de caractères.
Voyez plutôt:

char *machaine;
machaine = "coucou";

Que c'est il passé ici? C'est très simple. Nous avons déclaré un espace de type "tableau de char" dans notre mémoire grâce aux guillemets que nous avons ajouté lors de la définition de la valeur du pointeur "machaine". Le pointeur pointe donc sur l'adresse du premier caractère. (ici, le premier 'c')
Notre pointeur va donc pouvoir se comporter comme un tableau, puisqu'un tableau est un pointeur.
Voyez par exemple:

machaine[0]; //renvois c
machaine[4]; //Renvois o
machaine[7]; // provoquera un segfault
// Ici, je change la valeur d'une des cases par une autre valeur:
machaine[0] = 'A';// Ma chaine vaut donc "Aoucou"!
// Je peut aussi procéder comme ceci:
*(machaine + (0 * sizeof(char)) = 'A';

Voila, je viens de vous inculquer les bases de la gestion de pointeurs et de tableaux.
A bientôt pour un prochain cours!
Cours écrit par AlexMog. Contact: alexmog [at] live [point] fr

  • Upvote 3
Lien vers le commentaire
Partager sur d’autres sites

Alors là, merci. J'avais commencé le C, et j'ai juste ragequit quand j'suis arrivé aux pointeurs. Sachant que l'année prochaine, je vais à Epitech, faudra que je maitrise au minimum le C (Pas envie de crouler dès le début) Merci bien ^^

Pas de soucis ;) Et ne t'inquiète pas, en allant à Epitech, tu n'aura pas besoin de savoir grand chose en arrivant ;)

Lien vers le commentaire
Partager sur d’autres sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Invité
Répondre à ce sujet…

×   Vous avez collé du contenu avec mise en forme.   Supprimer la mise en forme

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Chargement
 Share

×
×
  • Créer...