C_facile : Introduction au langage C
Cours

Problème de conversion implicite et conversion explicite

Nous allons aborder le problème important en C des conversions réalisées par le compilateur au sein des expressions. Elles sont dites implicites

Exemple

int x = 3, y = 2; // déclaration de deux variables entières x et y et initialisation float z; // déclaration d'une variable flottante z z = x/y;

int x = 3, y = 2;

// déclaration de deux variables entières x et y et initialisation

float z; //

déclaration d'une variable flottante z

z = x/y;

Le contenu de z va être 1.0 et non pas 1.5. Ce contenu est logique si l'on connaît la manière dont le langage C réalise la compilation et mène les évaluations.

En premier lieu, rappelons qu'une variable entière n'est pas codée de la même manière qu'une variable flottante. Au niveau des instructions du micro processeur il y a des opérations en arithmétique entières et des opérations en arithmétique flottante.

Les opérations comme +, - , * et / par exemple ne sont pas réalisées de la même façon selon que les opérandes sont entières ou flottantes. Quand le compilateur rencontre l'expression x/y il choisit d'effectuer une opération soit en arithmétique entière soit en arithmétique flottante. Observons ce qui déclenche le choix.

Méthode

Les règles sont simples :

Si les opérandes sont de même type, l'instruction sera traitée à la compilation en fonction de ce type : arithmétique entière ou (exclusif) arithmétique flottante. Si les opérandes sont de types différents (entier et flottant) le compilateur choisira de traiter l'instruction en arithmétique flottante

Dans l'exemple ci-dessus, x et y sont entiers. C'est la division entière qui sera choisie, c'est-à-dire le résultat de la division Euclidienne en mathématique.

L'expression x/y s'évaluera à la valeur entière 1. Ce résultat sera ensuite affecté à la variable flottante z.

Les deux formats entier et flottant ne sont pas les mêmes. Le compilateur va donc automatiquement générer une instruction de conversion de type et il va mettre en place une conversion du résultat entier 1 en un flottant 1.0 puis ensuite ranger cette valeur dans la variable z.

En résumé, le compilateur choisit le type d'instructions arithmétiques en fonction des opérandes et en plus il effectue des opérations de conversion de format qui sont implicites (entière ou flottante).

ExempleAutre exemple

int x, y = 2;

// declaration de deux variables entieres x et y et initialisation

float z = 3.0;

// declaration d'une variable flottante z

x = z/y;

A l'exécution la variable x contiendra la valeur 1.

Voici comment le compilateur travaille :

  • Il constate que z est un flottant (le type de la variable est connu)

  • Il constate que y est un entier (le type de la variable est connu)

  • Il choisir d'effectuer une instruction de division flottante

  • Le type de y n'est pas compatible avec une instruction de division flottante

  • Le compilateur génère automatiquement une instruction de conversion pour transformer y qui contient une valeur entière en une valeur flottante qu'il pourra utiliser pour l'instruction de division flottante.

Attention

La variable y est toujours un entier, sa valeur sera convertie au sein même du microprocesseur en une valeur flottante, aucune variable supplémentaire n'est créée, la valeur intermédiaire créée n'existe qu'au sein du microprocesseur que le temps nécessaire pour effectuer le calcul.

Ceci est donc dynamique et temporaire.

  • Le résultat de l'évaluation de l'expression z/y sera un flottant.

  • L'instruction d'affectation simple veut ranger cette valeur dans une variable de type entier (le type de la variable est connu).

  • Il constate que les deux formats de données ne sont pas compatibles.

  • Le compilateur génère automatiquement une nouvelle instruction de conversion pour transformer le résultat de l'expression qui est une valeur flottante en une valeur entière.

  • Finalement, il met en place l'instruction pour ranger cette dernière valeur au sein de la variable entière x.

Complément

A l'exécution, voici ce qui ce passe : La valeur de z est 3.0, la valeur de y est 2, elle est dynamiquement convertie en 2.0, puis le calcul 3.0/2.0 est effectué, on obtient 1.5 (c'est un flottant), puis la valeur 1.5 (flottant) est convertie en la valeur entière 1 (troncature), la valeur 1 obtenue est rangée dans la variable x.

Le contenu de la variable x est désormais 1 (entier). Comme vous pouvez le constater, cette simple instruction "x = z/y;" induit des comportements par défaut du compilateur.

Il faut les connaître car ils peuvent être une source importante d'erreur quand on débute en langage C.

Attention

La conversion d'entier en flottant s'effectue sans perte d'information. La conversion de flottant en entier s'effectue avec des troncatures, donc avec perte d'informations.

En résumé : si les opérandes sont de type différents c'est le type le plus "large" qui est choisi.

Les conversions de type peuvent être maîtrisées par le programmeur grâce à des demandes explicites de conversion de type. C'est ce que l'on appelle en C les opérations de « cast ».

Exemple

int x = 3, y = 2;

// déclaration de deux variables entières x et y et initialisation

float z, t ;

// déclaration d'une variable flottante z

t = (float )x;

// demande explicite de conversion de x, entier en une valeur flottante

// que l'on range dans la variable t qui est un flottant, t contient 3.0

z = t/y;

// t est un flottant, donc arithmétique flottante donc la valeur de y est dynamiquement

// Convertie en valeur flottante pour mener à bien le calcul.

// L'expression retourne 1.5 et donc la variable z contient 1.5 (flottant)

z = (float)x/y ; // cette instruction fera le même travail

z = x/(float ) y; // et celle-ci aussi

ComplémentEn résumé

Pour demander explicitement la conversion d'une valeur d'une expression dans un type voulu, il suffit d'utiliser la syntaxe : (<type>) devant l'expression, sachant que <type> doit être un type prédéfini.

A ce niveau de connaissance, nous pouvons utiliser par exemple (int), (char), (float) comme opérateurs de « cast ». L'opérateur « cast » est opérateur unaire.

Priorité des opérateurs (page suivante)"adresse de" et "contenu de" (page Précédente)
AccueilImprimer creativecommons : by-nc-ndRéalisé avec SCENARI