précédent  index  suivant

10. Expressions


10.1 Le type Booléen existe-t-il en C ?

Oui, il existe un type booléen en C. C'est un ajout de la dernière version de la norme (C99). Il s'agit du type _Bool défini dans <stdbool.h>. Cet en-tête contient également les définitions de true et false. Une macro bool est souvent définie comme équivalent à _Bool.

Rappelons également qu'en C, une valeur est « fausse » si elle est nulle (ou équivalent), et « vraie » sinon. Les définitions de true et false suivent cette règle. Ainsi, la valeur entière de true est 1 et celle de false est 0.

10.2 Un pointeur NULL est-il assimilé à une valeur fausse ?

Oui, la valeur NULL est apparentée à un 0. Les écritures if(p != NULL) et if(p) sont donc équivalentes. De même, if(p == NULL) est équivalent à if(!p).

Voir aussi les questions 10.1 et 7.5.

10.3 Que donne l'opérateur ! sur un nombre négatif ?

L'opérateur ! sur un nombre négatif donne bien ce que l'on attend, à savoir 0.

Voir aussi la question 10.1.

10.4 Que vaut l'expression a[i] = i++ ?

Ce genre d'expression fait partie des « undefined behaviour », ou comportement indéfini. Cela signifie que le résultat d'une telle opération dépend du compilateur. L'opérateur ++ modifie la valeur de i, alors que celle-ci est utilisée ailleurs dans l'expression. C'est ce que l'on appelle un « effet de bords ».

10.5 Pourtant, i++ vaut i ?

Effectivement, i++ vaut i, avant l'incrémentation. Toutefois, rien ne dit dans quel sens est calculée l'expression a[i] = i++. Est-ce le i++ qui est évalué avant le a[i], ou le contraire ? On n'en sait rien, c'est pourquoi l'on dit que c'est un comportement indéfini.

10.6 En est-il de même pour i++ * i++ ?

Oui. La norme ne précise pas pour les opérateurs binaires dans quel ordre les opérandes sont évalués.

10.7 Peut-on utiliser les parenthèses pour forcer l'ordre d'évaluation d'une expression ?

Pas en général. Les parenthèses ne donnent qu'un ordre partiel d'évaluation, entre les opérateurs. Voici un petit exemple :

	a = f() + g() * h();
	b = (f() + g()) * h();
		

Les parenthèses dans la deuxième expression modifient l'ordre d'évaluation de l'addition et de la multiplication. Par contre, l'ordre dans lequel seront évaluées les fonctions est indéfini, dans l'une ou l'autre des deux expressions. Cela ne dépend que du compilateur.

Pour forcer un ordre d'évaluation, il faut utiliser une écriture séquentielle, avec des variables temporaires.

	tf = f();
	tg = g();
	th = h();
	b = (tf + tg) * th;
		

On a alors un comportement parfaitement défini sur toutes les cibles, quel que soit le compilateur.

10.8 Qu'en est-il des opérateurs logiques && et || ?

Ces deux opérateurs forment une exception à la règle. La norme prévoit que les opérandes de ces deux opérateurs soient évalués de gauche à droite. De plus, l'évaluation s'arrête dès que le résultat est connu.

10.9 Comment sont évaluées les expressions comprenant plusieurs types de variables ?

Le principe est simple. Si les variables sont de types différents, il y aura un cast implicite vers le type le plus précis. On parle de promotion. Voici les règles de base :

En C99, il faut rajouter le type long long.

Cela se complique dans le cas d'opérandes unsigned. Les comparaisons entre valeurs signées et non signées dépendent de la machine et de la taille des différents types.

10.10 Qu'est-ce qu'une lvalue ?

lvalue est un terme qui est utilisé pour définir les expressions que l'on peut mettre à gauche d'une affection. Toute variable modifiable est une lvalue.

Quand le compilateur prévient que le membre gauche d'une affectation n'est pas une lvalue, c'est souvent parce que l'on ne voulait pas faire une affectation, mais une comparaison (cf. 15.5).


précédent  index  suivant