|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nous approchons de la fin de notre tour d'horizon du langage C avec les opérateurs. Comment ça, déjà ? Le C est un langage assez concis ; il y a peu de choses dedans mais elles sont très puissantes : c'est à partir des notions que nous avons déjà vues et des opérateurs que sont construites les innombrables fonctions des bibliothèques de l'Amiga ou du compilateur, et qui ne font pas, à proprement parler, partie du langage C. L'opérateur d'affectation "=" Il ressemble à tous les "=" des autres langages :
...signifie que "a" reçoit la valeur de "b". Mais il y a plus fort :
...signifie que "a", "b", "c", "d" et "e" prennent la valeur de "f". Attention aussi à ne pas utiliser dans un test :
Ce piège est mortel pour les débutants... Cela signifie : "a" reçoit la valeur de "b" ; si cette valeur est vraie, alors exécuter instruction. Cette ligne représente une affectation et un test ! Les opérateurs mathématiques Ce sont les classiques "+", "-", "*", "/" et "%". "%" est le symbole du modulo, c'est-à-dire, le reste de la division entière : 15 % 4 = 3. Bien entendu, ces opérateurs sont utilisables avec tous les types de variables numériques et les règles de priorités qui s'appliquent sont celles communément admises en mathématiques : de gauche à droite, avec priorité aux parenthèses, puis aux multiplications et divisions. Les opérateurs d'incrémentation et de décrémentation Il est courant dans un programme que l'on doive ajouter ou retrancher 1 à une variable. Or, les microprocesseurs disposent d'une instruction d'incrémentation/décrémentation bien plus rapide que le chargement de 1 dans un registre suivi d'une addition. Dans certaines parties où la vitesse est primordiale, la différence entre les deux opérations pour arriver au même résultat peut être sensible (il s'agit généralement des indices de boucle). Plutôt que d'écrire :
...il est plus judicieux d'écrire :
Remarquez qu'il est possible d'écrire i++ et ++i, qui représentent respectivement la post-incrémentation et la pré-incrémentation. Ceci signifie que l'opération est effectuée après ou avant l'évaluation de l'ensemble de l'expression. Exemple pour fixer les idées :
1) b est incrémenté. 2) a reçoit le produit de b et de c. 3) c est décrémenté. Ces opérateurs marchent sur tous les types entiers (short, int, long, signés ou pas) ou char, mais pas sur les réels. Et je vous demande pourquoi ? Hmmm? Voyez dans un précédent article la structure d'un nombre réel : un certain nombre de bits est réservé à l'exposant, le reste à la mantisse. Par conséquent, ajouter 1 à un réel ne se fait pas par incrémentation d'un registre et n'est donc pas une opération aussi simple que dans le cas d'un entier. Les opérateurs de comparaison Le test d'égalité se fait avec "==". Par exemple :
Attention à ne pas écrire (a = b), je rappelle que c'est une affectation. Le test d'inégalité s'écrit "!=".
Les autres tests de comparaison sont les habituels ">", ">=", "<" et "<=". Les opérateurs logiques Ce sont les classiques "et", "ou" et "non", respectivement représentés ici par "&&", "||" et "!". Ils sont utilisés pour combiner plusieurs tests :
Je vous rappelle qu'il n'y a pas en C de booléens à proprement parler mais que cette notion est simulée par des entiers. "0" représente la valeur faux, toutes les autres valeurs signifiant vrai. On peut ainsi tester un entier utilisé comme un booléen :
Opérateurs sur les bits Lorsque vous désirez travailler sur des formules binaires, comme c'est souvent le cas en assembleur, vous pouvez utiliser ces opérateurs. Le C vous propose le "complément" (~), le "et" (&), le "ou" (|), le "ou exclusif" (^) et les décalages sur lesquels nous allons revenir. Il ne faut pas confondre ces opérateurs sur les bits avec les opérateurs logiques : "!" n'a rien à voir avec "~", "&" avec "&&" et "|" avec "||". Par exemple, "a = b && c;" signifie que "a" vaudra vrai si "b" et "c" valent vrai. Par contre, "a = b & c;" signifie que "a" reçoit le résultat de l'opération et entre les bits de "b" et ceux de "c". Le complément (~) consiste à inverser l'état des bits de la variable considérée : ceux qui étaient à 0 passent à 1 et vice-versa. Enfin, les décalages sont une astuce souvent utilisée en assembleur ; on les retrouve aussi en C. Ils s'écrivent sous ces deux formes :
"expression1" représente la valeur d'une variable ou le résultat d'un calcul, qui va être décalé d'un certain nombre de zéros, donné par "expression2". Il faut noter que "expression2" n'est pas forcément une constante. Les deux expressions doivent obligatoirement être d'un type entier ou caractère ; les flottants et doubles sont exclus. Je vous vois venir, vous allez me dire : "Mais il y a les décalages logiques et les décalages arithmétiques". Pouf pouf. Je ne disais rien, histoire de voir si vous suiviez. Les décalages arithmétiques s'appliquent aux variables signées ; les décalages logiques aux variables non signées. Ceci parce que, pour les variables signées, le premier bit représente le signe. Il doit être conservé par le décalage, d'où une technique différente du décalage logique où on ne s'occupe pas du bit de signe. Entre les deux types de décalage, que choisir ? Vous n'avez pas le choix : le compilateur connaît le type de vos variables (signées ou pas) et il sait donc quel décalage appliquer. Petite astuce bien connue, les décalages sont souvent utilisés pour réaliser des multiplications ou divisions par deux ou des puissances de deux. Car l'instruction de décalage du langage machine est bien plus rapide que celle de multiplication (quand elle existe, ce qui est heureusement le cas pour la famille des 680x0). Par exemple :
Les affectations combinées Lorsque, dans un calcul, la variable recevant le résultat est la même que la variable utilisée pour le calcul, il y a la possibilité, pour le compilateur, de générer un code optimisé. En généralisant, on peut dire que chaque fois que l'on trouve "a = a op b;" on a plutôt intérêt à écrire "a op= b;" ce qui est strictement équivalent. Exemples : "i = i + 5;" sera avantageusement remplacé par "i += 5;". Et "x = x/10;" par "x /= 10;". Les opérateurs combinés sont donc les suivants : "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "|=" et "^=". Le fait que le compilateur puisse générer un code optimisé peut permettre un gain de temps d'exécution et de taille du programme, modeste certes, mais il ne faut pas cracher dans la soupe. D'un autre côté, il s'agit plus sur notre machine, d'un style de programmation que d'une réelle nécessité. En effet, vous pouvez avoir intérêt à le faire en vue du portage de votre programme sur un autre ordinateur. Mais sur Amiga, j'ose espérer que les compilateurs C (au moins le Manx et le Lattice) sont suffisamment malins pour détecter tout seuls ce genre d'optimisation. L'expression conditionnelle Cette possibilité du C est assez peu utilisée car on n'y pense généralement pas : il n'y a rien d'équivalent dans les autres langages classiques. Elle réunit un test et deux valeurs, dont une sera sélectionnée suivant le résultat du test. Si la condition est vraie, la valeur choisie sera la première ; dans le cas contraire, ce sera la seconde. La forme générale est la suivante :
Exemple :
Ceci signifie que "valeur_absolue" va prendre la valeur de "x" si "x" est positif, ou la valeur de "-x" dans le cas contraire. Dans cette affectation, le test est effectué en premier ; suivant le résultat, une des deux valeurs est sélectionnée pour réaliser l'affectation. C'est sioux, non ? Cette possibilité est d'autant plus intéressante qu'elle ne marche pas que pour les affectations : chaque fois qu'une expression doit être évaluée, elle peut être utilisée. Voici une suggestion d'utilisation pour illustrer mes propos quelque peu abscons, dussé-je avouer (j'adore m'exprimer pompeusement) : il arrive que l'on veuille afficher le nom d'un objet et la quantité correspondante. Par exemple, "Actions Paribas: 6". Mais voilà, si ayant besoin d'argent pour acheter un disque dur ou de Vanessa Paradis, vous avez vendu cinq Paribas (en plus, c'est idiot car elles ont monté depuis), vous afficherez "Actions Paribas: 1". Et là, vous vous couvrez de ridicule devant la première personne à qui vous montrez le programme : "Eh, gros nase, si t'en as qu'une, faut pas de "s" à "actions", cong" (c'est certainement un Toulousain). Je n'ajouterai qu'une chose : la solution.
Le "%c" représente un caractère à afficher, la valeur de ce caractère étant donnée par le premier paramètre qui suit le format : "(nombre>1)?'s':''" Lorsque cet argument de la fonction printf devra être évalué, le programme comparera le nombre à 1. Suivant le résultat de ce test, le caractère à afficher sera un "s" ou un blanc. Il faut penser à utiliser cette tournure car elle peut servir très souvent. Vous pouvez même emboîter ainsi deux expressions, voire plus, dans le style :
Ceci signifie que :
Bon, je sens qu'il est temps que je m'arrête. Le mois prochain, nous parlerons de conversions de type et d'autres billevesées néanmoins fort intéressantes. Tout ceci bien sûr, si j'arrive à échapper aux hommes en blanc qui me poursuivent.
|