Une variable est un emplacement de la mémoire dans lequel est stockée une valeur. Chaque variable porte une nom et c’est ce nom qui sert à identifier l’emplacement de la mémoire représenté par cette variable. Pour utiliser une variable, la première étape est la déclaration.
Déclarer une variable, c’est prévenir le compilateur qu’un nom va être utilisé pour désigner un emplacement de la mémoire. En C, on déclare les variables juste après l’accolade suivant main() (pour le moment). On place les instructions à exécuter à la suite de la déclaration de variables.
main() { <declaration de variables> <instructions a executer> }
Nous ne travaillerons pour le moment que sur les variables de type
numérique entier. Le type qui y correspond, en C, est
int
. On
déclare les variables entières de la manière suivante :
int <var_1>, <var_2>, ..., <var_n>;
Cette instruction déclare les variables
var_1, var_2, ..., var_n
de type entier. Par exemple,
#include<stdio.h> int main() { int variable1, variable2; int autrevariable1, autrevariable2; return 0; }
On appelle bloc le contenu des accolades du main.
Si on souhaite affecter à la variable
v
une valeur, on
utilise l’opérateur
=
. Par exemple,
int main() { int v; v = 5; return 0; }
Ce programme déclare une variable de type entier que l’on appelle
v
, puis lui affecte la valeur 5. Comme vous venez de le
voir, il est possible d’écrire directement dans le code une valeur que
l’on donne à une variable. Notez l’abscence de
include
, ce
programme n’effectue aucune entrée-sortie, il n’est donc pas
nécessaire d’importer les bibliothèques d’entrées/sorties.
Les opérations arihmétiques disponibles sont l’addition (
+
),
la soustraction (
-
), la multiplication (
*
), la
division entière dans l’ensemble des entiers relatifs (quotient :
/
, reste :
%
).
int main() { int v, w, z; v = 5; w = v + 1; z = v + w / 2; v = z % 3; v = v * 2; return 0; }
Traduisons en C l’instruction
Saisir <variable>
que nous avons
vu en algorithmique. Pour récupérer la saisie d’un utilisateur et la
placer dans une variable
<variable>
, on utilise l’instruction
suivante :
scanf("%d", &<variable>);
scanf
suspend l’exécution du programme jusqu’à ce que
l’utilisateur ait saisi une valeur et pressé la touche
return
. La valeur saisie est alors affetée à la variable
<variable>
. N’oubliez surtout pas le
\&
,
sinon des choses absurdes pourraient se produire !
Traduisons maintenant l’instruction
Afficher variable
en
C. Cette instruction permet d’afficher la valeur d’une variable.
printf("%d", <variable>);
Cette instruction affiche la valeur contenue dans la variable
variable
(ne vous laissez pas impressionner par l’apparente
complexité de cette instruction !). Nous avons étendu, en
algorithmique, l’instruction
Afficher
en intercalant des
valeurs de variables entre les messages affichés. Il est possible
de faire de même en C :
printf("la valeur de la variable v est %d", v);
Cette instruction substitue à
%d
la valeur de la variable
v. Il est possible de l’étendre à volonté :
printf("les valeurs des variables x, y et z sont %d, %d et %d", x, y, z);
Cette instruction substitue à chaque
%d
les valeurs des
trois variables
x
,
y
et
z
.
Par exemple, le programme suivant
#include<stdio.h> int main() { int a, b, c; a = 1; b = 2; c = 3 printf("La valeur de a est %d, celle de b est %d, et celle de" "c est %d.", a, b, c); return 0; }
affiche
La valeur de a est 1, celle de b est 2, et celle de c est 3.
Trois types de base servent à représenter les entiers :
nom | taille (t) | nombre de valeurs (28t) | chaîne de format |
short | 1 octet | 28 valeurs | %hd |
int | 2 octets | 216 valeurs | %d |
long | 4 octets | 232 valeurs | %ld |
Par défaut, les entiers permettent de stocker des valeurs de signe
quelconque. Si on préfixe un type entier par
unsigned
, on le
restreint à des valeurs uniquement positives. Dans ce cas, on a
nom | taille (t) | nombre de valeurs (28t) | valeur min | valeur max | format |
unsigned short | 1 octet | 28 valeurs | 0 | 28 − 1 | %hu |
unsigned int | 2 octets | 216 valeurs | 0 | 216 − 1 | %u |
unsigned long | 4 octets | 232 valeurs | 0 | 232 − 1 | %lu |
La plage de valeur d’un
unsigned short
, encodée en binaire,
est
{0000 0000, 0000 0001, 0000 0010, 0000 0011, …, 1111 1110, 1111 1111} |
Si par contre les données sont signées, on a comme plage de valeurs
nom | taille (t) | nombre de valeurs (28t) | plus petite valeur | plus grande valeur |
short | 1 octet | 28 valeurs | −27 | 27 − 1 |
int | 2 octets | 216 valeurs | −215 | 215 − 1 |
long | 4 octets | 232 valeurs | −231 | 231 − 1 |
La plage de valeur d’un
short
, encodée en binaire, est aussi
{0000 0000, 0000 0001, 0000 0010, 0000 0011, …, 1111 1110, 1111 1111} |
Même si les codages sont les mêmes, la signification ne l’est pas, les nombres entiers positifs sont codés sur l’intervalle :
{0000 0000, 0000 0001, 0000 0010, 0000 0011, …, 0111 1100, 0111 1101, 0111 1110, 0111 1111} |
Et les nombres négatifs sur l’intervalle
{1000 0000, 1000 0001, 1000 0010, 1000 0011, …, 1111 1100, 1111 1101, 1111 1110, 1111 1111} |
Les nombres négatifs sont disposés du plus grand jusqu’au plus petit, l’intervalle précédent code les valeurs :
{−27, −(27 − 1), −(27 − 2), −(27 − 3), …, −4, −3, −2, −1} |
Les opérations arithmétiques sont exécutées assez bêtement, si vous calculez 0111 1111 + 0000 0001, ce qui correspond à (27 − 1) + 1, le résultat mathématique est 27, ce qui se code 1000 0000, ce qui est le codage de −27. Soyez donc attentifs, en cas de dépassement de capacité d’un nombre entier, vous vous retrouverez avec des nombres qui ne veulent rien dire. Si vous souhaitez faire des calculs sur des réels, un type flottant sera davantage adapté.
Les flottants servent à représenter les réels. Leur nom vient du fait qu’on les représente de façon scientifique : un nombre décimal (à virgule) muni d’un exposant (un décalage de la virgule). Trois types de base servent à représenter les flottants :
nom | taille | chaîne de format |
float | 4 octet | %f |
double | 8 octets | %f |
long double | 10 octets | %Lf |
Il est conventionel d’écrire des littéraux flottants avec un point,
par exemple l’approximation à 10−2 près de π s’ecrit
3.14
. Il est aussi possible d’utiliser la notation
scientifique, par exemple le décimal 1 000 s’écrit
1e3
, à
savoir 1.103.Nous nous limiterons à la description du type
float
, les autres types obéissent à des règles similaires.
float
Le codage d’un nombre de type
float
(32 bits) est découpé
en trois parties :
partie | taille |
le bit de signe | 1 bit |
l’exposant | 8 bits |
la mantisse | 23 bits |
Le nombre est positif si le bit de signe est à 0, négatif si le bit de signe est à 1. La mantisse et l’exposant sont codés en binaire, la valeur absolue d’un flottant de mantisse m et d’exposant e est m/223.2e. Le plus grand entier qu’il est possible de coder sur 23 octets est (223 − 1)/223, le plus grand exposant est 27 , donc le plus grand flottant est (223 − 1)/223.2(27), donc le plus petit est −(223 − 1)/223.2(27).
Un
char
sert à représenter le code ASCII d’un
caractère, il est donc codé sur 1 octet. Il est possible d’affecter
à une telle variable toute valeur du code ASCII entourée de
simples quotes. Par exemple, l’affectation suivante place dans
a
le code ASCII du caractère
'B'
.
char a; a = 'B';
De la même façon que l’on code des nombres entiers sur 1 octet avec
un
short
, un
char
contient avant tout un nombre codé
sur 1 octet. Pour afficher le caractère corrspondant au code
ASCII stocké dans un
char
, on utilise la chaîne de
format
%c
, et pour afficher le code ASCII lui-même
on utilise la chaîne de format
%d
. Si on souhaite manipuler
des
char
comme des nombres, le type
unsigned char
permet de coder des valeurs positives sur 1 octet, alors que
char
code aussi bien des nombres positifs que négatifs. Par
conséquent, les caractères de code ASCII 255 et 128
correspondent aux
unsigned char
de valeurs 255 et 128 et
aux
char
de valeurs −1 et −128.
Une constante est une valeur portant un nom, contrairement aux
variables, elles ne sont pas modifiables. Les constantes en C sont non
typées, on les définit dans l’entête de
la source, juste en dessous des
#include
. La syntaxe est
#define <NOM_CONSTANTE> <valeurConstante>
, par exemple
#define N 25
définit une constante N qui a la valeur
25. Au début de la compilation, un programme appelé
préprocesseur effectue un rechercher/remplacer et substitue à
toutes les occurences de
<NOM_CONSTANTE>
la valeur
<valeurConstante>
. Faites donc très attention au fait que
dans l’exemple présent, le préprocesseur va remplacer tous les N par
des 25. Donc si une variable s’appelle N, le préprocesseur va
le remplacer par un 25 ! Si par exemple vous écrivez
#include<stdio.h> #define N 25 int main() { int N; N = 12; printf("N = %d", N); return 0; }
Le préprocesseur va le transformer en
#include<stdio.h> #define N 25 int main() { int 25; 25 = 12; printf("N = %d", 25); return 0; }
Vous remarquez que les seules exceptions sont les valeurs délimitées
par des
"
.