pdf - e-book - archive - github.com

1.2  Variables

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.

1.2.1  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.

1.2.2  Affectation

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;
}

1.2.3  Saisie

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 !

1.2.4  Affichage

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.

1.2.5  Entiers

Trois types de base servent à représenter les entiers :

nomtaille (t)nombre de valeurs (28t)chaîne de format
short1 octet28 valeurs%hd
int2 octets216 valeurs%d
long4 octets232 valeurs%ld

Entiers non signés

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

nomtaille (t)nombre de valeurs (28t) valeur minvaleur maxformat
unsigned short1 octet28 valeurs028 − 1 %hu
unsigned int2 octets216 valeurs0216 − 1%u
unsigned long4 octets232 valeurs0232 − 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}

Entiers signés

Si par contre les données sont signées, on a comme plage de valeurs

nomtaille (t)nombre de valeurs (28t)plus petite valeurplus grande valeur
short1 octet28 valeurs−2727 − 1
int2 octets216 valeurs−215215 − 1
long4 octets232 valeurs−231231 − 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é.

1.2.6  Flottants

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 :

nomtaillechaîne de format
float4 octet%f
double8 octets%f
long double10 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.

Représentation en mémoire d’un float

Le codage d’un nombre de type float (32 bits) est découpé en trois parties :

partietaille
le bit de signe1 bit
l’exposant8 bits
la mantisse23 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).

1.2.7  Caractères

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.

1.2.8  Constantes

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 ".