Le langage C offre un opérateur d'incrémentation qui peut être utilisé soit
de manière préfixé, soit de manière postfixé.
Cet opérateur se note ++ et s'applique à une lvalue.
Sa syntaxe d'utilisation est donc au choix, soit
++ lvalue (utilisation en préfixé), soit
lvalue ++ (utilisation en postfixé).
Tout comme l'opérateur d'affectation, l'opérateur d'incrémentation réalise
à la fois un effet de bord et délivre une valeur :
++ lvalue incrémente lvalue de 1 et délivre cette nouvelle
valeur.
lvalue ++ incrémente lvalue de 1 et délivre la valeur
initiale de lvalue.
i = 0; t[i++] = 0; /* met à zéro l'élément d'indice 0 */ t[i++] = 0; /* met à zéro l'élément d'indice 1 */ i = 1; t[++i] = 0; /* met à zéro l'élément d'indice 2 */ t[++i] = 0; /* met à zéro l'élément d'indice 3 */
Il existe également un opérateur de décrémentation qui partage avec l'opérateur incrément les caractéristiques suivantes :
Cet opérateur se note - et décrémente la lvalue de 1 :
- lvalue décrémente lvalue de 1 et délivre
cette nouvelle valeur.
lvalue - décrémente lvalue de 1 et délivre
la valeur initiale de lvalue.
i = 9; t[i--] = 0; /* met à zéro l'élément d'indice 9 */ t[i--] = 0; /* met à zéro l'élément d'indice 8 */ i = 8; t[--i] = 0; /* met à zéro l'élément d'indice 7 */ t[--i] = 0; /* met à zéro l'élément d'indice 6 */
On a vu qu'une des formes d'instruction possibles en C est :
expression ;
et que cela n'a de sens que si l'expression réalise un effet de bord.
Les opérateurs ++ et - réalisant précisément un effet de bord,
permettent
donc d'écrire des instructions se réduisant à une expression utilisant
un de ces opérateurs.
Une incrémentation ou une décrémentation de variable se fait classiquement en
C de la manière suivante :
i++; /* incrémentation de i */ j--; /* décrémentation de j */
for (i = 0; i < N; i++) { ... }
expression :
expression1 &&
expression2
expression1 est évaluée et :
&&
rend la valeur 0 ;
&&
rend
la valeur 0 si expression2 est nulle, et 1 sinon.
On voit donc que l'opérateur &&
réalise le et logique de expression1 et
expression2 (en prenant pour faux la valeur 0, et pour vrai toute valeur
différente de 0).
On a la certitude que expression2 ne sera pas évaluée si expression1 rend la valeur faux. Ceci présente un intérêt dans certains cas de parcours de tableau ou de liste de blocs chaînés. Par exemple dans le cas d'un parcours de tableau à la recherche d'un élément ayant une valeur particulière, supposons que l'on utilise comme test de fin de boucle l'expression
i < n && t[i] != 234(on boucle tant que ce test est vrai), où
i < n
est le test permettant de ne pas déborder du tableau,
et t[i] != 234
est le test de l'élément recherché.
S'il n'existe dans le tableau aucun élément égal à 234,
il va arriver un moment où on va
évaluer i < n && t[i] != 234
avec i = n
.
La sémantique de l'opérateur &&
assurant que
l'expression t[i] != 234
ne sera pas évaluée,
on ne court donc pas le risque d'avoir une erreur matérielle
(t[n]
peut référencer une adresse mémoire invalide).
int a,b; if (a > 32 && b < 64) ... if ( a && b > 1) ... b = (a > 32 && b < 64);
expression :
expression1 ||
expression2
expression1 est évaluée et :
||
délivre la valeur 0 sinon elle délivre la valeur 1.
On voit donc que l'opérateur ||
réalise le ou logique de ses
opérandes,
toujours avec les mêmes conventions pour les valeurs vrai et faux, à savoir
0 pour faux, et n'importe quelle valeur non nulle pour vrai.
Dans ce cas également, on a la certitude que le second opérande ne sera pas
évalué si le premier délivre la valeur vrai.
int a,b; if (a > 32 || b < 64) ... if ( a || b > 1) ... b = (a > 32 || b < 64);
expression :
!
expression
expression est évaluée, si sa valeur est nulle, l'opérateur !
délivre
la valeur 1, sinon il délivre la valeur 0.
Cet opérateur réalise le non logique de son opérande.