Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Vous êtes un professionnel et vous avez besoin d'une formation ? Programmation avec
Le langage C
Voir le programme détaillé

Chaînes de caractères et buffers

Les types et les variables Les expressions et les opérateurs


Accès rapide :
Le caractère nul terminal
Prévoir la taille d'un buffer
Chaînes littérales et chaînes modifiables
Copies et concaténations

En C, une chaîne de caractères n'est pas un type de données autonome comme cela peut être le cas dans d'autres langages. Il s'agit simplement d'une suite de caractères stockée dans un tableau, et terminée par un caractère nul : '\0'. Cette règle est simple, mais elle impose de toujours raisonner sur la taille des buffers manipulés.

Le caractère nul terminal

Une chaîne C doit toujours se terminer par '\0'. On parle parfois de chaîne AZT, acronyme anglais de ASCII Zero Terminated. En français, l'expression a été francisée en « chaîne à zéro terminal ». Cette terminologie est historique : l'idée importante est que la fin de la chaîne n'est pas stockée dans un champ de taille, mais détectée grâce au caractère nul terminal. Les fonctions de la librairie standard, comme strlen, parcourent donc la mémoire jusqu'à rencontrer ce caractère. S'il manque, votre programme continuera à lire au-delà de la zone prévue, avec un comportement indéfini à la clé.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
#include <stdio.h>

int main() {

    char message[] = { 'K', 'o', 'o', 'R', '\0' };
    printf( "%s\n", message );

    return 0;
}
Une chaîne C est terminée par le caractère nul

Prévoir la taille d'un buffer

Lorsque vous réservez un buffer, vous devez prévoir la place pour les caractères utiles, mais aussi pour le caractère nul terminal. Pour stocker une chaîne de dix caractères, il faut donc un tableau d'au moins onze cases.

Dans la pratique, préférez les fonctions qui reçoivent explicitement la taille du buffer. Par exemple, snprintf permet de produire une chaîne formatée sans dépasser la capacité disponible.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
#include <stdio.h>

int main() {

    char buffer[32];
    int value = 123;

    snprintf( buffer, sizeof buffer, "value == %d", value );
    printf( "%s\n", buffer );

    return 0;
}
Construction d'une chaîne dans un buffer

Chaînes littérales et chaînes modifiables

Il est important de ne pas confondre un pointeur vers une chaîne littérale et un tableau de caractères. Une chaîne littérale, comme "KooR", est généralement stockée dans une zone mémoire non modifiable. Le compilateur peut accepter le code ci-dessous, mais son exécution produit un comportement indéfini.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
#include <stdio.h>

int main() {

    char * name = "KooR";
    name[0] = 'B';

    printf( "%s\n", name );

    return 0;
}
Modification interdite d'une chaîne littérale
$> gcc -Wall -o Sample Sample.c
$> ./Sample
Segmentation fault (core dumped)
$>

La bonne solution consiste à placer la chaîne dans un tableau de caractères. Dans ce cas, le tableau contient une copie modifiable des caractères de la chaîne, y compris le caractère nul terminal.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
#include <stdio.h>

int main() {

    char name[] = "KooR";
    name[0] = 'B';

    printf( "%s\n", name );

    return 0;
}
Copie modifiable d'une chaîne
attention toutefois : dans cet exemple, le tableau name est une variable locale. Il est donc stocké sur la pile (la stack), qui reste une zone mémoire limitée. Pour des chaînes très longues ou des buffers volumineux, préférez une allocation dynamique ou un stockage global/statique adapté.

Copies et concaténations

Les fonctions historiques comme strcpy et strcat supposent que le buffer de destination est assez grand. Elles sont donc très faciles à mal employer. Dans un programme réel, la bonne habitude consiste à conserver la taille du buffer à proximité du buffer lui-même, et à vérifier cette taille à chaque écriture.

Ce chapitre ne remplace pas les pages de référence de <string.h>, mais il doit vous faire retenir une idée simple : en C, manipuler une chaîne revient aussi à manipuler une zone mémoire.

Les types et les variables Les expressions et les opérateurs




Vous êtes un professionnel et vous avez besoin d'une formation ? Programmation avec
Le langage C
Voir le programme détaillé