Comment travailler avec les variables, les types de données et les expressions arithmétiques dans le langage de programmation C

Le C possède une riche variété d’opérateurs mathématiques que vous pouvez utiliser pour manipuler vos données. Dans ce chapitre de Programming in C, 4th Edition, Stephen G. Kochan couvre les types de données int, float, double, char, et _Bool, la modification des types de données avec short, long, et long long, les règles pour nommer les variables, les opérateurs mathématiques de base et les expressions arithmétiques, et le type casting.

Le véritable pouvoir des programmes que vous créez est leur manipulation des données. Afin de vraiment profiter de cette puissance, vous devez mieux comprendre les différents types de données que vous pouvez utiliser, ainsi que la façon de créer et de nommer les variables. Le C dispose d’une riche variété d’opérateurs mathématiques que vous pouvez utiliser pour manipuler vos données. Dans ce chapitre, vous couvrirez :

  • Les types de données int, float, double, char, et _Bool
  • Modifier les types de données avec short, long, et long long
  • Les règles pour nommer les variables
  • Opérateurs mathématiques de base et expressions arithmétiques
  • Casting de type

Comprendre les types de données et les constantes

Vous avez déjà été exposé au type de données de base C int. Comme vous vous en souvenez, une variable déclarée de type int peut être utilisée pour contenir des valeurs intégrales uniquement – c’est-à-dire des valeurs qui ne contiennent pas de décimales.

Le langage de programmation C fournit quatre autres types de données de base : float, double, char, et _Bool. Une variable déclarée de type float peut être utilisée pour stocker des nombres à virgule flottante (valeurs contenant des décimales). Le type double est identique au type float, mais avec une précision environ deux fois supérieure. Le type de données char peut être utilisé pour stocker un seul caractère, comme la lettre ‘a’, le chiffre ‘6’ ou le point-virgule (‘;’) (nous y reviendrons plus tard). Enfin, le type de données _Bool peut être utilisé pour stocker uniquement les valeurs 0 ou 1. Les variables de ce type sont utilisées pour indiquer une situation de type on/off, oui/non, ou vrai/faux. Ces choix un ou l’autre sont également connus comme des choix binaires.

En C, tout nombre, caractère unique ou chaîne de caractères est connu comme une constante. Par exemple, le nombre 58 représente une valeur entière constante. La chaîne de caractères « Programming in C is fun.\n » est un exemple de chaîne de caractères constante. Les expressions entièrement constituées de valeurs constantes sont appelées expressions constantes. Ainsi, l’expression

128 + 7 - 17

est une expression constante car chacun des termes de l’expression est une valeur constante. Mais si i était déclaré comme étant une variable entière, l’expression

128 + 7 – i

ne représenterait pas une expression constante car sa valeur changerait en fonction de la valeur de i. Si i vaut 10, l’expression est égale à 125, mais si i vaut 200, l’expression est égale à -65.

Le type entier int

En C, une constante entière est constituée d’une séquence d’un ou plusieurs chiffres. Un signe moins précédant la séquence indique que la valeur est négative. Les valeurs 158, -10 et 0 sont toutes des exemples valides de constantes entières. Aucun espace n’est autorisé entre les chiffres, et les valeurs supérieures à 999 ne peuvent pas être exprimées par des virgules. (Ainsi, la valeur 12 000 n’est pas une constante entière valide et doit être écrite comme 12000.)

Deux formats spéciaux en C permettent aux constantes entières d’être exprimées dans une base autre que décimale (base 10). Si le premier chiffre de la valeur entière est un 0, l’entier est considéré comme exprimé en notation octale, c’est-à-dire en base 8. Dans ce cas, les autres chiffres de la valeur doivent être des chiffres valides en base 8 et, par conséquent, doivent être compris entre 0 et 7. Ainsi, pour exprimer la valeur 50 en base 8 en C, qui est équivalente à la valeur 40 en décimal, on utilise la notation 050. De même, la constante octale 0177 représente la valeur décimale 127 (1 × 64 + 7 × 8 + 7). Une valeur entière peut être affichée sur le terminal en notation octale en utilisant les caractères de format %o dans la chaîne de format d’une instruction printf(). Dans ce cas, la valeur est affichée en octal sans le zéro initial. Le caractère de format %#o entraîne l’affichage d’un zéro de tête devant une valeur octale.

Si une constante entière est précédée d’un zéro et de la lettre x (en minuscule ou en majuscule), la valeur est considérée comme étant exprimée en notation hexadécimale (base 16). Immédiatement après la lettre x se trouvent les chiffres de la valeur hexadécimale, qui peuvent être composés des chiffres 0-9 et des lettres a-f (ou A-F). Les lettres représentent les valeurs 10-15, respectivement. Ainsi, pour attribuer la valeur hexadécimale FFEF0D à une variable entière appelée rgbColor, on peut utiliser l’instruction

rgbColor = 0xFFEF0D;

. Les caractères de format %x affichent une valeur au format hexadécimal sans le 0x de tête, et en utilisant les lettres minuscules a-f pour les chiffres hexadécimaux. Pour afficher la valeur avec le 0x de tête, vous utilisez les caractères de format %#x, comme dans ce qui suit :

printf ("Color is %#x\n", rgbColor);

Un x majuscule, comme dans %X ou %#X, peut être utilisé pour afficher le x de tête et les chiffres hexadécimaux qui suivent en utilisant des lettres majuscules.

Tailles et plages de stockage

Chaque valeur, qu’il s’agisse d’un caractère, d’un nombre entier ou d’un nombre à virgule flottante, a une plage de valeurs qui lui est associée. Cette plage a trait à la quantité de stockage qui est allouée pour stocker un type particulier de données. En général, cette quantité n’est pas définie dans le langage. Elle dépend généralement de l’ordinateur que vous utilisez, et est donc dite dépendante de l’implémentation ou de la machine. Par exemple, un nombre entier peut occuper 32 bits sur votre ordinateur, ou bien être stocké sur 64 bits. Vous ne devriez jamais écrire de programmes qui font des hypothèses sur la taille de vos types de données. Vous avez toutefois la garantie qu’une quantité minimale de mémoire sera réservée à chaque type de données de base. Par exemple, il est garanti qu’une valeur entière sera stockée dans un minimum de 32 bits de stockage, ce qui est la taille d’un « mot » sur de nombreux ordinateurs.

Le type de nombre flottant float

Une variable déclarée de type float peut être utilisée pour stocker des valeurs contenant des décimales. Une constante à virgule flottante se distingue par la présence d’un point décimal. Vous pouvez omettre les chiffres avant la virgule ou les chiffres après la virgule, mais vous ne pouvez évidemment pas omettre les deux. Les valeurs 3., 125,8 et -.0001 sont toutes des exemples valables de constantes à virgule flottante. Pour afficher une valeur à virgule flottante sur le terminal, on utilise les caractères de conversion printf %f.

Les constantes à virgule flottante peuvent également être exprimées en notation scientifique. La valeur 1,7e4 est une valeur à virgule flottante exprimée dans cette notation et représente la valeur 1,7 × 104. La valeur précédant la lettre e est appelée la mantisse, tandis que la valeur qui suit est appelée l’exposant. Cet exposant, qui peut être précédé d’un signe plus ou moins facultatif, représente la puissance de 10 par laquelle la mantisse doit être multipliée. Ainsi, dans la constante 2,25e-3, 2,25 est la valeur de la mantisse et -3 est la valeur de l’exposant. Cette constante représente la valeur 2,25 × 10-3, soit 0,00225. Au passage, la lettre e, qui sépare la mantisse de l’exposant, peut être écrite en minuscule ou en majuscule.

Pour afficher une valeur en notation scientifique, il faut spécifier les caractères de format %e dans la chaîne de format printf(). Les caractères de format printf() %g peuvent être utilisés pour laisser printf() décider s’il faut afficher la valeur en virgule flottante en notation flottante normale ou en notation scientifique. Cette décision est basée sur la valeur de l’exposant : Si elle est inférieure à -4 ou supérieure à 5, le format %e (notation scientifique) est utilisé ; sinon, le format %f est utilisé.

Utilisez les caractères du format %g pour afficher les nombres à virgule flottante – il produit la sortie la plus esthétique.

Une constante flottante hexadécimale est constituée d’un 0x ou 0X de tête, suivi d’un ou plusieurs chiffres décimaux ou hexadécimaux, suivi d’un p ou P, suivi d’un exposant binaire éventuellement signé. Par exemple, 0x0,3p10 représente la valeur 3/16 × 210 = 0,5.

Le type précision étendue double

Le type double est très similaire au type float, mais il est utilisé chaque fois que la plage fournie par une variable float n’est pas suffisante. Les variables déclarées de type double peuvent stocker environ deux fois plus de chiffres significatifs qu’une variable de type float. La plupart des ordinateurs représentent les valeurs doubles en utilisant 64 bits.

Sauf indication contraire, toutes les constantes à virgule flottante sont prises comme des valeurs doubles par le compilateur C. Pour exprimer explicitement une constante flottante, ajoutez un f ou un F à la fin du nombre, comme suit :

12.5f

Pour afficher une valeur double, on peut utiliser les caractères de format %f, %e ou %g, qui sont les mêmes caractères de format utilisés pour afficher une valeur flottante.

Le type de caractère unique char

Une variable char peut être utilisée pour stocker un caractère unique.1 Une constante de caractère est formée en enfermant le caractère dans une paire de guillemets simples. Ainsi, ‘a’, ‘;’ et ‘0’ sont tous des exemples valides de constantes de caractères. La première constante représente la lettre a, la deuxième est un point-virgule et la troisième est le caractère zéro – qui n’est pas le même que le chiffre zéro. Ne confondez pas une constante de caractère, qui est un caractère unique entre guillemets simples, avec une chaîne de caractères, qui est un nombre quelconque de caractères entre guillemets doubles.

La constante de caractère ‘\n’-le caractère de nouvelle ligne- est une constante de caractère valide même si elle semble contredire la règle citée précédemment. Cela est dû au fait que le caractère backslash est un caractère spécial dans le système C et ne compte pas réellement comme un caractère. En d’autres termes, le compilateur C traite le caractère ‘\n’ comme un seul caractère, même s’il est en réalité formé de deux caractères. Il existe d’autres caractères spéciaux qui sont initiés avec le caractère backslash. Consultez l’annexe A, « Résumé du langage C », pour une liste complète.

Les caractères de format %c peuvent être utilisés dans un appel printf() pour afficher la valeur d’une variable char au terminal.

Le type de données booléen _Bool

Une variable _Bool est définie dans le langage comme étant suffisamment grande pour stocker uniquement les valeurs 0 et 1. La quantité précise de mémoire utilisée n’est pas spécifiée. Les variables _Bool sont utilisées dans les programmes qui doivent indiquer une condition booléenne. Par exemple, une variable de ce type peut être utilisée pour indiquer si toutes les données ont été lues dans un fichier.

Par convention, 0 est utilisé pour indiquer une valeur fausse, et 1 indique une valeur vraie. Lors de l’affectation d’une valeur à une variable _Bool, une valeur de 0 est stockée comme 0 à l’intérieur de la variable, tandis que toute valeur non nulle est stockée comme 1.

Pour faciliter le travail avec les variables _Bool dans votre programme, le fichier d’en-tête standard <stdbool.h> définit les valeurs bool, true et false. Un exemple est présenté dans le programme 5.10A du chapitre 5, « Prendre des décisions. »

Dans le programme 3.1, les types de données de base du C sont utilisés.

Programme 3.1 Utilisation des types de données de base

Programme 3.1 Sortie

integerVar = 100floatingVar = 331.790009doubleVar = 8.440000e+11doubleVar = 8.44e+11charVar = WboolVar = 0;

La première instruction du programme 3.1 déclare que la variable integerVar est une variable entière et lui attribue également une valeur initiale de 100, comme si les deux instructions suivantes avaient été utilisées à la place :

int integerVar;integerVar = 100;

Dans la deuxième ligne de la sortie du programme, remarquez que la valeur de 331,79, qui est attribuée à floatingVar, est en fait affichée comme 331,790009. En fait, la valeur réelle affichée dépend du système informatique particulier que vous utilisez. La raison de cette inexactitude est la manière particulière dont les nombres sont représentés en interne dans l’ordinateur. Vous avez probablement rencontré le même type d’inexactitude lorsque vous traitez des chiffres sur votre calculatrice de poche. Si vous divisez 1 par 3 sur votre calculatrice, vous obtenez le résultat .33333333, avec peut-être quelques 3 supplémentaires ajoutés à la fin. La chaîne de 3 est l’approximation de la calculatrice d’un tiers. Théoriquement, il devrait y avoir un nombre infini de 3. Mais la calculatrice ne peut contenir qu’un nombre limité de chiffres, d’où l’imprécision inhérente à la machine. Le même type d’imprécision s’applique ici : Certaines valeurs à virgule flottante ne peuvent pas être représentées exactement à l’intérieur de la mémoire de l’ordinateur.

Lorsque vous affichez les valeurs des variables flottantes ou doubles, vous avez le choix entre trois formats différents. Les caractères %f sont utilisés pour afficher les valeurs de manière standard. Sauf indication contraire, printf() affiche toujours une valeur flottante ou double avec six décimales arrondies. Vous verrez plus loin dans ce chapitre comment sélectionner le nombre de décimales affichées.

Les caractères %e sont utilisés pour afficher la valeur d’une variable flottante ou double en notation scientifique. Là encore, six décimales sont automatiquement affichées par le système.

Avec les caractères %g, printf() choisit entre %f et %e et supprime aussi automatiquement de l’affichage les zéros de queue. Si aucun chiffre ne suit le point décimal, il ne l’affiche pas non plus.

Dans l’avant-dernière instruction printf(), les caractères %c sont utilisés pour afficher le caractère unique ‘W’ que vous avez attribué à charVar lors de la déclaration de la variable. Rappelez-vous que, alors qu’une chaîne de caractères (comme le premier argument de printf()) est enfermée dans une paire de guillemets doubles, une constante de caractères doit toujours être enfermée dans une paire de guillemets simples.

Le dernier printf() montre qu’une variable _Bool peut voir sa valeur affichée en utilisant les caractères de format entier %i.

Spécificateurs de type : long, long long, court, non signé et signé

Si le spécificateur long est placé directement avant la déclaration int, la variable entière déclarée est de portée étendue sur certains systèmes informatiques. Un exemple de déclaration long int pourrait être

long int factorial;

Ceci déclare la variable factorielle comme étant une variable entière longue. Comme pour les flottants et les doubles, la précision particulière d’une variable longue dépend de votre système informatique particulier. Sur de nombreux systèmes, un int et un long int ont la même plage et l’un ou l’autre peut être utilisé pour stocker des valeurs entières jusqu’à 32 bits de large (231 – 1, ou 2 147 483 647).

Une valeur constante de type long int est formée en ajoutant facultativement la lettre L (majuscule ou minuscule) à la fin d’une constante entière. Aucun espace n’est autorisé entre le nombre et le L. Ainsi, la déclaration

long int numberOfPoints = 131071100L;

déclare la variable numberOfPoints de type long int avec une valeur initiale de 131 071 100.

Pour afficher la valeur d’un long int à l’aide de printf(), la lettre l est utilisée comme modificateur devant les caractères de format entier i, o et x. Cela signifie que les caractères de format %li peuvent être utilisés pour afficher la valeur d’un long int au format décimal, les caractères %lo peuvent afficher la valeur au format octal, et les caractères %lx peuvent afficher la valeur au format hexadécimal.

Il existe également un type de données entier long, alors

long long int maxAllowedStorage;

déclare la variable indiquée comme étant de la précision étendue spécifiée, qui est garantie d’être au moins 64 bits de large. Au lieu d’une seule lettre l, deux l sont utilisés dans la chaîne printf pour afficher des entiers longs, comme dans « %lli ».

Le spécificateur long est également autorisé devant une déclaration de double, comme suit :

long double US_deficit_2004;

Une constante double longue est écrite comme une constante flottante avec la lettre l ou L qui suit immédiatement, comme

1.234e+7L

Pour afficher un double long, le modificateur L est utilisé. Ainsi, %Lf affiche une valeur double longue en notation flottante, %Le affiche la même valeur en notation scientifique, et %Lg indique à printf() de choisir entre %Lf et %Le.

Le spécificateur short, lorsqu’il est placé devant la déclaration int, indique au compilateur C que la variable particulière déclarée est utilisée pour stocker des valeurs entières assez petites. La motivation pour l’utilisation de variables courtes est principalement une conservation de l’espace mémoire, ce qui peut être un problème dans les situations dans lesquelles le programme a besoin de beaucoup de mémoire et la quantité de mémoire disponible est limitée.

Sur certaines machines, un int court occupe la moitié de la quantité de stockage qu’une variable int régulière. Dans tous les cas, vous avez la garantie que la quantité d’espace allouée à un short int ne sera pas inférieure à 16 bits.

Il n’y a aucun moyen d’écrire explicitement une constante de type short int en C. Pour afficher une variable short int, placez la lettre h devant l’un des caractères normaux de conversion d’entier : %hi, %ho ou %hx. Alternativement, vous pouvez également utiliser n’importe lequel des caractères de conversion d’entier pour afficher les int courts, en raison de la façon dont ils peuvent être convertis en entiers lorsqu’ils sont passés comme arguments à la routine printf().

Le dernier spécificateur qui peut être placé devant une variable int est utilisé lorsqu’une variable entière sera utilisée pour stocker uniquement des nombres positifs. La déclaration

unsigned int counter;

déclare au compilateur que la variable compteur est utilisée pour contenir uniquement des valeurs positives. En limitant l’utilisation d’une variable entière au stockage exclusif d’entiers positifs, la précision de la variable entière est étendue.

Une constante int non signée est formée en plaçant la lettre u (ou U) après la constante, comme suit :

0x00ffU

On peut combiner les lettres u (ou U) et l (ou L) lors de l’écriture d’une constante entière, ainsi

20000UL

dit au compilateur de traiter la constante 20000 comme un long non signé.

Une constante entière qui n’est suivie d’aucune des lettres u, U, l, ou L et qui est trop grande pour tenir dans un int de taille normale est traitée comme un int non signé par le compilateur. S’il est trop petit pour tenir dans un int non signé, le compilateur le traite comme un long int. S’il ne peut toujours pas tenir dans un long int, le compilateur le transforme en unsigned long int. S’il ne rentre pas là, le compilateur le traite comme un long long int s’il rentre, et comme un unsigned long int sinon.

Lorsque vous déclarez des variables de type long long int, long int, short int, ou unsigned int, vous pouvez omettre le mot clé int. Par conséquent, la variable compteur non signée aurait pu être déclarée de manière équivalente comme suit :

unsigned counter;

Vous pouvez également déclarer les variables char comme étant non signées.

Le qualificateur signé peut être utilisé pour indiquer explicitement au compilateur qu’une variable particulière est une quantité signée. Son utilisation se fait principalement devant la déclaration char, et une discussion plus approfondie est reportée au chapitre 13, « More on Data Types. »

Ne vous inquiétez pas si les discussions de ces spécificateurs vous semblent un peu ésotériques à ce stade. Dans les sections ultérieures de ce livre, plusieurs de ces différents types sont illustrés par des exemples de programmes réels. Le chapitre 13 entre dans le détail des types de données et des conversions.

Le tableau 3.1 résume les types de données de base et les qualificatifs.

Tableau 3.1 Types de données de base

.