Pourquoi les programmes ont besoin de branches
Tous les programmes jusqu'ici se sont déroulés tout droit : ligne 1, ligne 2, ligne 3. Les vrais programmes prennent des décisions. Le mot de passe est-il correct ? Le nombre est-il négatif ? Le fichier s'est-il ouvert ? L'instruction if est la façon dont le C pose une question et n'exécute du code que si la réponse est oui.
La condition temperature > 30 est testée une fois. Elle tient, donc le message s'affiche. La dernière ligne est hors des accolades, elle s'affiche donc quoi qu'il arrive. Remplacez 31 par 18 et relancez - le premier message disparaît et le second reste.
Syntaxe : parenthèses, accolades et pas de point-virgule
Un if en C a une forme figée :
if (condition) {
// s'execute quand condition est non nulle
}
Trois règles à mémoriser tôt. Les parenthèses autour de la condition sont obligatoires. Il n'y a pas de mot-clé then. Et il n'y a pas de point-virgule après la parenthèse fermante - un point-virgule égaré termine l'instruction sur place :
// BUG: le if ne fait rien ; le printf s'execute toujours
if (x > 10);
{
printf("grand\n");
}
Cela compile sans broncher. Le ; est une instruction vide qui devient le corps du if, et les accolades en dessous ne sont qu'un bloc autonome qui s'exécute toujours. Compiler avec gcc -Wall l'attrape.
Les accolades elles-mêmes sont facultatives pour une instruction unique, mais laissez-les. Un if sans accolades qui gagne une seconde ligne plus tard est une source classique de bugs, car l'indentation ne groupe pas les instructions en C.
else et else if
else fournit l'autre chemin :
Pour plus de deux issues, chaînez avec else if. Le C vérifie chaque condition dans l'ordre et s'arrête à la première qui tient :
L'ordre compte énormément ici. Parce que la chaîne s'arrête à la première correspondance, le deuxième test ne voit jamais que des scores inférieurs à 90 - c'est pourquoi score >= 80 n'a pas besoin de dire aussi && score < 90. Écrivez la chaîne de la condition la plus restrictive à la moins restrictive, ou toutes les valeurs tomberont dans la première branche.
Le else final est facultatif. Incluez-en un dès que la chaîne est censée couvrir tous les cas ; son absence signifie « si rien ne correspond, ne rien faire », ce qui est très bien mais doit être délibéré.
La véracité : 0 est faux, tout le reste est vrai
Le cœur du langage C n'a pas de type booléen distinct dans les conditions. Un if demande simplement si l'expression est non nulle.
Les deux dernières lignes montrent l'autre moitié de la règle : les opérateurs de comparaison sont des expressions ordinaires qui produisent 1 pour vrai et 0 pour faux. C'est pourquoi if (5 > 2) fonctionne - c'est en réalité if (1).
C'est aussi pourquoi -3 est vrai en C. La règle est non nul, pas positif. Si vous voulez savoir si un nombre est positif, écrivez if (n > 0), pas if (n).
C99 a ajouté <stdbool.h> avec un vrai type bool plus true et false, ce qui se lit mieux dans du code neuf. En dessous, ils valent toujours 1 et 0, donc rien de la règle ci-dessus ne change - voir Les booléens en C.
Les opérateurs de comparaison et logiques que vous utiliserez dans les conditions :
== egal a && ET logique (les deux cotes vrais)
!= different de || OU logique (l'un ou l'autre vrai)
< inferieur a ! NON logique
> superieur a
<= inferieur ou egal
>= superieur ou egal
&& et || évaluent en court-circuit : a && b n'évalue jamais b si a est faux, et a || b n'évalue jamais b si a est vrai. C'est une garantie, pas une optimisation, on peut donc écrire sans crainte if (n != 0 && total / n > 5) - la division ne peut pas s'exécuter quand n vaut zéro.
Le bug = contre ==
C'est l'erreur la plus courante dans les conditions C :
// BUG: affecte 5 a x, puis teste 5 (non nul), donc ceci s'execute TOUJOURS
if (x = 5) {
printf("x vaut cinq\n");
}
Le C autorise l'affectation dans une expression, donc la ligne est légale. Elle stocke 5 dans x, produit la valeur 5, et 5 est non nul - la branche s'exécute à chaque fois, et x a été discrètement écrasé.
Deux défenses. D'abord, compilez toujours avec les avertissements activés :
gcc -Wall -Wextra program.c -o program
GCC et clang signalent tous deux « suggest parentheses around assignment used as truth value ». Ensuite, certains programmeurs écrivent la constante avant la variable - if (5 == x) - de sorte qu'un if (5 = x) mal tapé soit une erreur de compilation franche plutôt qu'un bug silencieux. Ce style relève du goût ; activer les avertissements non.
L'imbrication
Un if peut en contenir un autre. L'imbrication exprime des conditions qui n'ont de sens qu'une fois une condition antérieure vérifiée :
Deux niveaux restent lisibles. Quatre non. Quand l'imbrication s'approfondit, cherchez à l'aplatir - souvent en combinant les conditions avec &&, ou en traitant d'abord les cas d'échec et en retournant tôt :
// plus plat : traiter les exceptions, puis passer au travail
if (age < 18) { printf("Reserve aux adultes.\n"); return 0; }
if (!hasTicket) { printf("Veuillez acheter un billet.\n"); return 0; }
printf("Bienvenue.\n");
Le else pendouillant
Quand un if sans accolades est imbriqué dans un autre, à quel if appartient un else ? La règle du C : un else s'attache au if non apparié le plus proche, quelle que soit l'indentation du code.
// Le else appartient au if INTERNE, malgre l'indentation
if (a > 0)
if (b > 0)
printf("les deux positifs\n");
else
printf("a n'est pas positif\n"); // FAUX - s'execute quand a > 0 et b <= 0
L'indentation dit que le else s'apparie au if externe. Le compilateur l'apparie à l'interne. Les accolades suppriment entièrement l'ambiguïté, ce qui est le vrai argument pour toujours les utiliser :
if (a > 0) {
if (b > 0) {
printf("les deux positifs\n");
}
} else {
printf("a n'est pas positif\n");
}
L'opérateur ternaire
Quand une branche n'existe que pour choisir une valeur, l'opérateur conditionnel ? : le dit en une expression :
Lisez cond ? x : y comme « si cond alors x sinon y ». Exactement une des deux branches est évaluée, et l'ensemble produit une valeur - c'est pourquoi il peut être affecté ou passé en argument là où une instruction ne le pourrait pas.
Gardez-le pour des choix de valeurs simples. Les ternaires imbriqués (a ? b : c ? d : e) sont légaux et presque toujours plus difficiles à lire que la chaîne else if qu'ils remplacent.
Questions fréquentes
Comment écrit-on une instruction if else en C ?
Mettez la condition entre parenthèses et le code entre accolades : if (score >= 60) { printf("Reussi\n"); } else { printf("Echoue\n"); }. Le bloc else ne s'exécute que quand la condition est fausse, et il n'y a pas de mot-clé then en C.
Qu'est-ce qui compte comme vrai dans un if en C ?
Toute valeur non nulle. Le C n'a pas de type booléen dédié dans sa syntaxe de base, donc if (n) s'exécute quand n vaut autre chose que 0, et if (!n) ne s'exécute que quand n vaut exactement 0. Les opérateurs de comparaison comme == et < produisent 1 pour vrai et 0 pour faux.
Quelle est la différence entre = et == en C ?
== compare, = affecte. Écrire if (x = 5) affecte 5 à x puis teste 5, qui est non nul, donc la branche s'exécute toujours. Cela compile sans erreur, ce qui en fait le bug de débutant le plus courant dans les conditions C - la plupart des compilateurs le signalent avec -Wall.
Comment fonctionne l'opérateur ternaire en C ?
condition ? valeurSiVrai : valeurSiFaux est une expression qui produit l'une de deux valeurs, elle peut donc tenir dans une affectation ou un argument de printf : int max = a > b ? a : b;. Utilisez-le pour choisir une valeur, et un if classique quand vous devez exécuter des instructions.