ProgrammationDéveloppeur C embarqué

Décrivez les particularités du travail avec le modificateur const pour les paramètres de fonction et les variables locales en C. Comment const influence-t-il le passage de pointeurs et de références sur les données, et quelle est la différence entre les différentes modifications de const dans les déclarations de fonction ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

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 :

  • exprimer clairement les intentions du développeur,
  • simplifier la lecture et la maintenance du code,
  • créer des interfaces sûres pour travailler avec la mémoire.

Exemple de code

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 piège

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

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


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.