• Aucun résultat trouvé

L’opérateur d’affectation usuel

Dans le document Programmer en Java (Page 84-88)

Les opérateurs et les expressions

6 L’opérateur d’affectation usuel

Nous avons déjà eu l'occasion de remarquer que i = 5 était une expression qui :

• réalisait une action : l'affectation de la valeur 5 à i,

• possédait une valeur : celle de i après affectation, c'est-à-dire 5.

Cet opérateur d'affectation (=) peut faire intervenir d'autres expressions, comme dans : c = b + 3

La faible priorité de cet opérateur = (elle est inférieure à celle de tous les opérateurs arithmé-tiques et de comparaison) fait qu'il y a d'abord évaluation de l'expression b + 3. La valeur ainsi obtenue est ensuite affectée à c.

6.1 Restrictions

Comme on s’y attend, il n'est pas possible de faire apparaître une expression comme premier opérande de cet opérateur =. Ainsi, l'expression suivante n'aurait pas de sens :

c + 5 = x

D’une manière générale, l’opérateur d’affectation impose que son premier opérande soit une référence à un emplacement dont on peut effectivement modifier la valeur. Pour l’instant, nous savons que les variables répondent à une telle condition, pour peu qu’elles ne soient pas déclarées avec l’attribut final. Plus tard, nous verrons que l’opérateur d’affectation peut aussi s’appliquer à des objets1 ou à des éléments d’un tableau2.

1. Cependant, dans ce cas, il portera sur les références aux objets et non sur leurs valeurs.

2. En C/C++, il existe beaucoup plus de possibilités pour l’affectation (en particulier, par le biais de pointeurs), ce qui impose de définir un terme (en général lvalue) pour désigner les expressions auxquelles on peut l’appliquer.

6.2 Associativité de droite à gauche

Contrairement à tous ceux que nous avons rencontrés jusqu'ici, cet opérateur d'affectation possède une associativité de droite à gauche. C'est ce qui permet à une expression telle que :

i = j = 5

d'évaluer d'abord l'expression j = 5 avant d'en affecter la valeur (5) à la variable j. Bien entendu, la valeur finale de cette expression est celle de i après affectation, c'est-à-dire 5.

6.3 Conversions par affectation

6.3.1 Généralités

Considérons ces instructions :

int n, p ; ...

n = p + 5 ;

On affecte une valeur de type int (résultat du calcul de l’expression p+5) à une variable n du même type. Aucun problème ne se pose.

Considérons maintenant :

float x ; int p ; ...

x = p + 5 ;

Cette fois, on demande d’affecter une valeur de type int à une variable de type float. Java l’accepte, moyennant simplement la mise en place d’une conversion de int en float, compara-ble à celle qui peut intervenir dans une conversion d’ajustement de type, dont on sait qu’elle ne dégrade pas (trop) la valeur.

En revanche, les choses sont moins satisfaisantes avec ces instructions :

int n ; float x ; ...

n = x + 5 ;

En effet, l’affectation sera cette fois rejetée en compilation. Java refuse de convertir une valeur de type float en int, du moins lorsqu’on ne le lui demande pas explicitement, ce qui est le cas ici1.

D’une manière générale, les conversions qui sont permises lors d’une affectation sont celles qui ne modifient pas la valeur d’origine ou qui la modifient peu. Ce sont celles que l’on a déjà rencontrées à la fois dans les promotions numériques et dans les conversions d’ajustement de type avec, en plus, des possibilités de conversion de byte en short. On peut résumer cela en

1. Nous verrons plus loin comment imposer explicitement une telle conversion.

disant que les conversions implicites sont celles qui se font suivant l’une des deux hiérarchies suivantes :

Les conversions implicites légales

Remarques

1 Parmi les conversions légales, on trouve celle de char en int, mais pas celle de char en short. En effet, bien que ces deux types soient de même taille, le type short est destiné à des nombres relatifs avec signe, tandis que, par convention, la conversion d’une valeur de type char doit toujours fournir un résultat positif. Le type short s’avère alors trop petit pour accueillir toutes les valeurs possibles.

2 Les conversions de byte en char ou de short en char ne sont pas des conversions impli-cites légales.

3 Nous rencontrerons d’autres conversions légales par affectation à propos des objets et des tableaux.

4 Distinguez bien les conversions implicites mise en oeuvre automatiquement dans les calculs d’expression (conversions d’ajustement de type et promotions numériques) et les conversions implicites provoquées par une affectation. Les premières sont mises en place par le compilateur, les secondes par le programmeur. Notez toutefois que les pre-mières constituent un sous-ensemble des secondes.

En C++

En C/C++, toutes les conversions numériques sont légales par affectation. Certaines peuvent alors fortement dégrader les informations correspondantes...

6.3.2 Quelques conséquences

Les règles de promotions numériques de Java peuvent parfois avoir des conséquences insi-dieuses au niveau de l’affectation. En voici un exemple relatif aux promotions de byte en int :

int n ; short p ; byte b1, b2 ; ...

n = b1 * b2 ; // OK car l’expression b1 * b2 est de type int

p = b1 * b2 ; // erreur de compilation : on ne peut affecter int a short

Le remède, dans ce cas, consistera à recourir à une conversion forcée (cast) dont nous parle-rons au paragraphe 9.

byte --> short -> int -> long -> float -> dou le char -> int -> long -> float -> dou le

Par ailleurs, une conversion de int en float peut conduire à une légère perte de précision pour les grandes valeurs, comme le montre ce programme :

public class ErrConv

{ public static void main (String args[]) { int n ;

float x ; n = 1234 ; x = n ;

System.out.println ("n : " + n + " x : " + x) ; n = 123456789 ;

x = n ;

System.out.println ("n : " + n + " x : " + x) ; }

}

n : 1234 x : 1234.0

n : 123456789 x : 1.23456792E8

Perte de précision dans la conversion int -> float

Si, par mégarde, vous faites afficher la valeur de x-n, vous obtiendrez 0, ce qui pourrait laisser croire à l’égalité des deux valeurs. En fait, vous ne faites que soustraire deux valeurs appro-chées (égales) de n, mais non égales à n. En revanche, en faisant appel à l’opérateur de cast présenté plus tard, vous pourriez procéder ainsi pour mettre en évidence l’erreur de conver-sion (avec les mêmes valeurs que dans le deuxième cas du programme précédent, vous obtiendrez un écart de 3) :

x = n ;

int na = (int) x

System.out.println ("ecart" + na-n) ;

6.3.3 Cas particulier des expressions constantes

Pour d’évidentes raisons de facilité d’écriture, Java autorise des affectations telles que celle-ci :

short p ; ...

p = 123 ; // accepté bien que 123 soit une constante de type int

D’une manière générale, vous pouvez affecter n’importe quelle expression constante entière1 à une variable de type byte, short ou char, à condition que sa valeur soit représentable dans le

1. La notion d’expression constante a été présentée au paragraphe 6.3.3 du chapitre .

type voulu (si ce n’est pas le cas, vous obtiendrez une erreur de compilation). Voici un autre exemple :

final int N = 50 ;

short p = N ; // OK : p reçoit la valeur 50

char c = 2*N + 3 ; // OK : c est le caractère de code 103 byte b = 10*N ; // erreur de compilation : 500 est supérieur // à la capacité du type byte

7 Les opérateurs d’incrémentation

Dans le document Programmer en Java (Page 84-88)