Les conversions silencieuses de C, et quand elles ne le sont pas
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 4 — Discipline de programmation, validation et test
Énoncé
Le chapitre affirme que ces trois lignes sont acceptées en C. Les compiler avec gcc -Wall -Wextra -std=c99, exécuter, puis recommencer avec les mêmes conversions faites depuis des variables. Que constate-t-on ?
int n = 3.9;
char c = 300;
int* p = (int*) &c;Corrigé
Depuis des constantes littérales, le compilateur parle :
warning: implicit conversion from 'double' to 'int' changes value
from 3.9 to 3 [-Wliteral-conversion]
warning: implicit conversion from 'int' to 'char' changes value
from 300 to 44 [-Wconstant-conversion]
--- execution ---
n = 3, c = 44, *p = 812
Les valeurs sont celles qu'annonce le cours : tronqué à , et ramené à (car ). La troisième ligne, elle, ne produit aucun avertissement : le transtypage explicite est une affirmation du programmeur, et le compilateur la croit. Elle lit quatre octets là où il n'y en a qu'un — la valeur obtenue ici n'a aucun sens et changera d'une exécution à l'autre.
Depuis des variables, le silence revient :
int lire(void) { return 300; }
int v = lire();
char c = v; /* la MEME conversion */
double d = 3.9;
int n = d; /* la MEME conversion */
gcc -Wall -Wextra : aucun avertissement, c = 44, n = 3
gcc -Wall -Wextra -Wconversion :
warning: implicit conversion loses integer precision: 'int' to 'char'
warning: implicit conversion turns floating-point number into integer
Ce que l'exercice corrige. Dire que C convertit « en silence » est trop rapide : sur une constante, le compilateur sait calculer la perte et la signale. Sur une valeur calculée, il ne peut plus rien dire sans l'option -Wconversion, qui n'est activée ni par -Wall ni par -Wextra. Or, dans un programme réel, les conversions dangereuses portent presque toujours sur des valeurs calculées.
En pratique — Les trois options qui devraient toujours être là
gcc -Wall -Wextra -Wconversion -std=c99 -fsanitize=address,undefined
-Wconversion attrape les conversions avec perte, et -fsanitize instrumente le programme pour qu'il s'arrête à l'endroit exact d'un débordement de tampon ou d'un comportement indéfini. Ce n'est pas de la superstition : ce sont les seuls outils qui rendent à C une partie des garanties qu'OCaml donne gratuitement. Le chapitre chap:langage-c les emploie déjà pour les fautes de mémoire.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.