« Programmation C/Opérateurs » : différence entre les versions

Contenu supprimé Contenu ajouté
mAucun résumé des modifications
Ligne 1 :
[[Catégorie:<noinclude>{{Programmation C (livre)]]}}</noinclude>
<noinclude>{{Programmation C}}
</noinclude>
== Les opérateurs du C ==
 
Les opérateurs du C permettent de former des expressions, expressions qui diront quoi faire à votre programme. On peut voir un programme C comme étant composé de trois catégories d'instructions&nbsp; :
* Les '''déclarations''' et '''définitions''' (variables, fonctions, types) : déclarent et définissent les objets que pourront manipuler le programme.
* Les '''expressions''' : manipulent les déclarations, via les opérateurs.
Ligne 15 ⟶ 13 :
Les opérateurs binaires et ternaires utilisent une notation infixe (l'opérateur se trouve entre les 2 ou 3 opérandes). Les opérateurs unaires s'écrivent de manière préfixé (avant l'opérande), à l'exception des opérateurs <code>++</code> et <code>--</code> qui peuvent s'écrire de manière préfixée ou suffixée (avec une différence subtile, décrite ci-après).
 
La '''priorité''' (quel opérateur est appliqué avant, en l'absence de parenthèses explicite) et l'<b>associativité</b> (dans quel ordre sont traités les arguments des opérateurs ayant la même priorité) sont résumées dans la table suivante (par ordre décroissant de priorité - les opérateurs décrits dans un autre chapitre ont un lien dédié)&nbsp; :
 
{| cellpadding="5" cellspacing="0" style="border:thin black solid"
Ligne 154 ⟶ 152 :
</source>
 
Il est important de noter que le langage ne fait que garantir qu'une variable post-incrémentée ou post-décrémentée acquiert sa nouvelle valeur entre le résultat de l'opérateur et le prochain point de séquencement atteint (généralement la fin d'une instruction). Mais on ne sait pas vraiment quand entre les deux. Ainsi, si l'objet sur lequel s'applique un tel opérateur apparaît plusieurs fois avant un point de séquencement, alors le résultat est '''imprévisible''' et son comportement peut changer simplement en changeant les options d'un même compilateur&nbsp; :
 
{{Erreur volontaire|nombre=2}}
Ligne 202 ⟶ 200 :
De toute évidence <code>a</code> est supérieur à <code>b</code> dans cet exemple. Et pourtant, si ce code est exécuté sur certaines architectures, il affichera <code>a &lt; b</code>, justement à cause de cette conversion.
 
Tout d'abord dans la comparaison <code>a &lt; b</code>, le type de <code>a</code> est « le plus grand », donc <code>b</code> est promu en <code>unsigned long</code>. C'est en fait ça le problème&nbsp; : -23 est une valeur négative, et la conversion d'une valeur négative en un type non signé se fait modulo la valeur maximale représentable par le type non signé + 1. Si la valeur maximale pour le type <code>unsigned long</code> est 2<sup>32</sup>-1, alors -23 est converti modulo 2<sup>32</sup>, et devient 4294967273 (soit 2<sup>32</sup>-23). Dans ce cas là effectivement 23 < 4294967273, d'où ce résultat surprenant.
 
À noter qu'on aurait eu le même problème si le type de <code>b</code> était <code>signed long</code>. En fait les types signés sont promus en non-signés, s'il y a au moins une variable non-signée dans l'expression, et que le type non-signé est "plus grand" que le type signé.
Ligne 273 ⟶ 271 :
</source>
 
Une autre technique classique, lorsqu'une comparaison fait intervenir une constante, est de mettre la constante à gauche. De cette manière, si la comparaison se transforme par mégarde en affectation, cela provoquera une erreur à la compilation&nbsp; :
 
<source lang="c">
Ligne 309 ⟶ 307 :
 
<noinclude>
 
== Notes ==
<references />
 
[[en:C Programming/Simple math]]
[[pl:C/Operatory]]
</noinclude>