ProgrammationDéveloppeur C

Quelles règles de conversion de types (conversion de type, promotion de type) s'appliquent dans les expressions en langage C ? Donnez des exemples d'erreurs inattendues et de solutions.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En langage C, les expressions subissent souvent des conversions de types (promotion de type, conversion de type), régies par les standards :

  • Promotion des entiers : les types de plus faible précision (par exemple, char, short) sont automatiquement convertis en int ou unsigned int avant les opérations arithmétiques.
  • Conversions arithmétiques habituelles : si les opérandes sont de types différents, ils sont convertis au "type plus large" selon des règles établies.
  • Dans les opérations mixtes avec des types signés et non signés, le résultat peut changer de manière inattendue à cause de la conversion.

Exemple :

unsigned short a = 65535; signed short b = -1; printf("%d ", a + b); // dépend de la conversion !

Recommandation : faites attention aux types des opérandes, surtout lors de l'utilisation d'opérations bit à bit, de longueurs de tableaux, d'indices, et évitez le mélange implicite de types signés et non signés.

Question piège

Que va afficher le fragment suivant ?

unsigned int u = 1; int i = -2; printf("%d ", u + i);

Réponse : La variable i sera convertie en unsigned int, la valeur finale sera très grande, car le résultat en interne sera : 1U + (unsigned int)-2U, ce qui donnera un nombre proche de UINT_MAX (4294967295). Un nombre négatif ne sera affiché que si printf est formaté comme int, sinon ce sera une valeur indéterminée.

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Dans le calcul des valeurs moyennes d'intensité d'image, int et unsigned int ont été confondus. Les valeurs négatives étaient mal transmises à travers unsigned, produisant d'énormes nombres et provoquant un débordement du tampon d'image.


Histoire

Dans un firmware embarqué, la longueur de la chaîne était calculée avec size_t, tandis que le tableau était indexé avec int. Lors de la vérification des conditions de dépassement de tableau, on comparait int i >= size_t len, ce qui brisait la logique pour les longues chaînes et provoquait des bugs dans la comparaison de différents types (size_t — unsigned).


Histoire

Un développeur sur un projet financier calculait le reste de la division pour les nombres négatifs avec %, oubliant que le signe du résultat pour des opérandes négatifs dépend de l'implémentation. Dans un environnement, le résultat était positif, dans un autre — négatif, ce qui faisait que les calculs "déraillaient" périodiquement.