const en langage C permet de limiter la modifiabilité d'un objet. Lorsqu'il est utilisé avec des paramètres de fonction, cela aide à protéger les données contre des modifications accidentelles. La principale différence dans la déclaration dépend de ce à quoi le modificateur const se rapporte et de sa position par rapport au pointeur.
Exemple de différentes déclarations :
void func(const int *ptr); // pointeur vers un int constant void func(int * const ptr); // pointeur constant vers un int void func(const int *const ptr); // pointeur constant vers un int constant
const int *ptr — les données ne peuvent pas être modifiées, le pointeur lui-même peut être réassigné.int *const ptr — les données peuvent être modifiées, mais le pointeur ne peut pas être réassigné.const int *const ptr — ni les données ni le pointeur ne peuvent être modifiés à l'intérieur de la fonction.Utilisation appropriée de const : permet de :
void print_array(const int *arr, size_t n) { for (size_t i = 0; i < n; ++i) { printf("%d\n", arr[i]); // arr[i] = 10; // erreur : tentative de modification des données const } }
Question : Peut-on assigner l'adresse d'une variable constante à un pointeur ordinaire ?
Réponse attendue incorrecte : "Oui, si nous supprimons const dans la déclaration du pointeur, le compilateur le permet."
Réponse correcte : Il est permis de "baisser const" uniquement avec un casting explicite, mais cela entraîne un comportement indéfini lors de la tentative de modification d'un objet déclaré comme const. Cela ne doit pas être fait — cela viole la sémantique de const et conduit à des erreurs d'exécution.
Exemple:
const int x = 5; int *ptr = (int*)&x; *ptr = 10; // UB : modification de l'objet const
Histoire
Dans un grand projet, un programmeur a tenté de contourner la protection const en castant un pointeur constant en un pointeur ordinaire et en modifiant des données dans la zone mémoire en lecture seule. Sur certaines plateformes, cela a entraîné un arrêt brutal du programme (segmentation fault), et sur d'autres, des erreurs invisibles, difficiles à déboguer.
Histoire
Dans une bibliothèque pour travailler avec un tableau, le développeur a oublié de déclarer les paramètres comme const. En conséquence, un appel incorrect de la fonction a accidentellement modifié les données d'origine, ce qui a entraîné une désynchronisation de l'état du tableau et des bugs graves dans les blocs de traitement suivants.
Histoire
Lors de l'écriture d'une fonction de rappel, transmise à une bibliothèque externe, on a oublié de spécifier const pour le tampon d'entrée. La bibliothèque a tenté de modifier les données dans une chaîne constante, ce qui a entraîné un plantage sur certains systèmes d'exploitation et de longues recherches de la source du problème.