next up previous contents index
suivant: La fonction main monter: main précédent: Types   Table des matières   Index


Nom, expression, instruction / valeur, objet, adresse

Un programme est une suite de déclarations de noms. Un nom sert à désigner un objet, une fonction, un type ou d'autres entités. Une déclaration introduit un nouveau nom et indique comment il doit être utilisé. Dans le cas d'un objet (par exemple, d'une variable ou d'un tableau) ou d'une fonction, les conditions d'utilisation du nom sont exprimées par un type. C'est la déclaration du nom qui permettra de vérifier que les noms sont employés correctement, notamment que les expressions sont bien typées. Une fois déclaré, un nom ne désigne pas encore une entité et ne peut donc pas être utilisé librement. C'est seulement après avoir été défini qu'un nom désigne une entité. Dans le cas d'un objet, une définition est une déclaration qui l'installe dans la mémoire et éventuellement l'initialise ; cette installation dans la mémoire est une opération importante qu'on appelle l'allocation. Dans le cas d'une fonction, une définition est une déclaration pourvue d'un corps de fonction.

Voici les définitions de deux noms de variable de type int, a et b, la seconde étant initialisée, d'un nom de tableau v de type << tableau de 3 double >>, d'un nom s de chaîne de caractères et d'un nom f de fonction:


int a;
int b = 4;
double v[3];
string s;
int f(int x) { return x*x; }

Les noms vont servir à construire des expressions, autre notion syntaxique : on trouvera en C++ des expressions arithmétiques (par exemple, a - 2*b), des expressions logiques (comme a<b/2 || a>=b), des affectations (comme a = b+1), des appels de fonction (comme f(a+b)), et bien d'autres, qui seront présentées ultérieurement, C++ étant un langage très riche en expressions. Les expressions sont destinées à être évaluées, c'est-à-dire à produire une valeur : 2+3 a pour valeur 5.

En particulier, un nom de variable est une expression dont la valeur doit être cherchée en mémoire, là où cette variable a été installée : pour évaluer b+1, il faut évaluer la variable b, donc savoir où b est rangée en mémoire, ce qui est déterminé par l'adresse de b. Quand la définition d'une variable ne comporte pas d'initialisation, elle ne devra pas être utilisée tant qu'une valeur ne lui aura pas été affectée. Faute d'une initialisation, la mémoire attribuée à une variable peut contenir des valeurs qui proviennent d'une autre utilisation de cette partie de la mémoire. Cette erreur de programmation est assez fréquente : on ne doit pas faire de la cuisine avec des détritus !

Pour évaluer une affectation, comme a = 2+3, la position de a à gauche de l'affectation fait que ce n'est pas la valeur de a qui doit être utilisée, mais son adresse. L'expression qui figure à droite du signe = est évaluée, puis la valeur obtenue, ici 5, est copiée << dans >> a. Ainsi un nom de variable a à la fois une valeur et une adresse, l'un ou l'autre étant utilisé selon la position du nom dans une expression. D'autres expressions peuvent être placées à gauche d'une affectation, de façon analogue aux noms de variable3 ; on en verra des exemples avec des tableaux, des structures et des pointeurs. Toutes les affectations gauche = droite ne sont pas correctement formées. Il est nécessaire que les types des deux expressions gauche et droite soient compatibles, en un sens que nous préciserons ultérieurement, et que le type de gauche ne soit pas un const $T$.

Plus généralement, certaines expressions ont une adresse : on dit que ces expressions désignent des objets. Soulignons que ce n'est pas le cas de toutes : $2+3$ a une valeur, mais pas d'adresse (la valeur, 5, n'est pas non plus un objet). Il faut bien distinguer valeur et objet : quand on définit


  int b = 4, c = b;

les expressions b et c ont la même valeur, qui est l'entier 4. Par contre b et c désignent des objets différents, au sens où ils occupent des zones différentes de la mémoire. C'est la valeur de b qui est copiée dans la zone mémoire attribuée à c.

Un objet a une existence dans l'espace et dans le temps. Dans l'espace, c'est une zone mémoire qui a été attribuée par allocation, dans le temps c'est la durée de vie, qui s'étend de l'allocation à la dés-allocation de cette zone mémoire. Il y a trois modes d'allocation d'un objet : statique, automatique, et dynamique. Pendant sa durée de vie, un objet a une adresse. Les objets ayant une allocation statique ou automatique sont désignés par un nom ; ceux ayant une allocation dynamique sont anonymes (mais peuvent être désignés par des expressions).

La mémoire peut être vue comme un tableau, à une dimension, dont les éléments sont des octets (c'est-à-dire des suites de 8 bits) ; chaque élément de ce tableau est indexé par une adresse. La figure 2 donne un aperçu d'une mémoire qui contiendrait trois objets de tailles différentes : le premier occupe un octet (probablement un objet de type char), le second occupe 8 octets (c'est peut-être un double, ou un tableau de deux float, etc), le troisième occupe 4 octets (peut-être un int, ou un tableau de quatre char, etc). Les octets entre ces objets ne sont pas alloués, mais contiennent des détritus provenant d'utilisations précédentes de la mémoire.


\begin{figurette}
% latex2html id marker 4532\begin{center}
\leavevmode
\fb...
.../memoire.eps}
} \caption {Un aperçu de la mémoire} \end{center} \end{figurette}

Enfin, les expressions servent à construire des instructions (en anglais statement), autre notion syntaxique importante dont le rôle est d'opérer sur la mémoire et de contrôler l'exécution du programme. Celles-ci ne peuvent figurer que dans le corps d'une fonction. Une instruction est soit une instruction simple, soit une instruction composée.

Toute expression suivie d'un << ; >> est une instruction simple ; notamment, une affectation suivie d'un << ; >> est une instruction ; un << return >> suivi d'une expression et d'un << ; >> est aussi une instruction simple.

Les instructions conditionnelles (if, switch), par exemple


    if (v <= f(u)) {
      k = k+1;
    }

et les instructions d'itération (for, while), par exemple


  for (i=1; i<=N; i++) {
    somme = somme + i;
  }

sont des instructions composées. Un bloc, formé d'une suite de déclarations et d'instructions4, et encadré par << { >> et << } >> est aussi une instruction composée ; le bloc suivant est formé des définitions de u et de v et d'une instruction conditionnelle :


{
    double 
      u = drand48(),
      v = drand48();
    if (v <= f(u)) {
      return true;
    } else {
      return false;
    }
}

Le corps d'une fonction est un bloc. Notons qu'un bloc peut être vide, on l'écrit simplement {}.


next up previous contents index
suivant: La fonction main monter: main précédent: Types   Table des matières   Index
R Lalement