Terminologie et syntaxe

Terminologie et syntaxe

Accolades

Le corps d'une fonction commence toujours par une accolade ouvrante ({) et se termine par une accolade fermante (}).

 

Adresse

A toute variable correspond l'adresse de l'endroit où elle est rangée en mémoire. La valeur de cette adresse est obtenue en faisant précéder le nom de la variable de la lettre &.

Exemple :
Si on a la déclaration
int v;
l'adresse de v est notée &v.

On peut aussi avoir des variables de type adresse déclarées de la façon suivante :
Exemple :
int * AdrEntier;
AdrEntier sera destinée à contenir l'adresse d'une variable de type int. Avec l'exemple ci-dessus, on pourra écrire:
AdrEntier=&v;

On peut aussi utiliser des variables de type adresse pure, adresse de rien de spécial, avec une déclaration du type
void * AdrPure;
mais cette variable AdrPure sera peu utilisable car, pour certaines opérations faites en mémoire, et en particulier pour la gestion des tableaux, la machine doit connaître le nombre d'octets nécessaire pour coder la variable qui se trouve à l'adresse indiquée.

 

Argument

On appelle ainsi les valeurs que l'on indique à une fonction pour que celle-ci puisse savoir sur quoi elle doit travailler, au moment de l'appel de cette fonction.
exemples :
  1. dans
       printf("bonjour");
    l'argument est la chaîne de caractères "bonjour"
  2. dans
       additionne(x,3);
    la fonction additionne admet deux
    paramètres, et on l'appelle en lui envoyant comme arguments la valeur de x et le nombre 3.

     

    Arguments sur la ligne de commande

    On peut indiquer deux paramètres à la fonction main qui permettent d'indiquer au programme certaines valeurs au moment de l'exécution.
    La compilation et l'édition de liens conduisent à la création d'un exécutable. Pour lancer l'exécution du programme, on peut utiliser ce qu'on appelle la "ligne de commande". Celle-ci se présente différemment selon l'environnement de travail. Sous Windows, on obtient la ligne de commande en cliquant sur "Executer" dans le menu "Fichier" du gestionnaire de programme. Si la fonction main a été définie avec des paramètres, il faut indiquer sur la ligne de commande le chemin d'accès de l'exécutable suivi des valeurs à transmettre au programme. On peut ausi lancer l'exécutable à partir du gestionnaire de fichier.
    Pour utiliser ce type de possibilité, deux paramètres exactement doivent figurer dans la fonction main.
    Le premier de ces paramètres, de type int, souvent appelé argc, prend pour valeurs le nombre d'arguments donnés sur la ligne de commande, en comptant le nom de l'exécutable lui-même.
    Le second paramètre, souvent appelé argv, est un pointeur sur un tableau de chaînes de caractères qui contiennent les arguments à raison de un par chaîne ; argv[0] contient le nom de l'exécutable.

     

    Bloc

    Un bloc est une partie de programme commençant par une accolade ouvrante ({) et se terminant par une accolade fermante (}). Un bloc ne peut se trouver que dans une fonction. Entre les accolades, on trouve éventuellement : des déclarations de variables locales, des instructions et des blocs.

     

    Caractères

    Un caractère est toujours indiqué entre des apostrophes.
    On manipule des caractères avec le type char, qui est codé sur un octet.
    L'indicateur de format pour les caractères est %c. :
     
    Exemples :
    • char lettre='a';
      La variable lettre, de type char, est définie et initialisé avec le caractére a.
       
    • putchar('/'');
      Conduit à l'écriture de '
       
    • char lettre;
      char mot[]="bonjour";
       
      lettre=mot[3];
      printf("%c",lettre);

      Conduit à l'écriture de j.

    Caractères spéciaux

    Les caractères spéciaux sont formés de deux symboles dont le premier est \ ; on a entre autres :
    • \n : passage à la ligne
    • \t : tabulation
    • \b : retour en arrière d'un caractère
    • \\ : pour écrire \
    • \" : pour écrire des guillemets (")
    • \' : pour écrire ' (utile uniquement quand on veut écrire le seul caractère ', mais pas à l'intérieur d'une chaîne de caractères)

     

    Chaîne de caractères


    Une chaîne de caractères est un tableau de
    caractères, terminé par le caractère "de valeur nulle" qui est noté '\0'.
    Les fonctions de saisie des bibliothèques, comme fgets ou comme scanf assortie de l'indicateur de format %s, respectent la convention du caractère \0 en fin de chaîne, en ajoutant ce caractère à la fin de la chaîne indiquée par l'utilisateur.
    Des guillemets en fin de ligne et en début de la ligne suivante permettent d'écrire une chaîne de caractères sur plusieurs lignes.

    Si MAXCAR a une valeur entière positive, l'instruction : char prenom[MAXCAR]; définit un tableau de caractères. L'adresse de ce tableau est donnée par la constante prenom et le la chaîne de caractères devra avoir au plus MAXCAR caractes autres que le caractère final de valeur nulle..

    On peut aussi écrire, par exemple :
    char chaine[]="bonjour";
    chaine est alors un tableau de longueur 8 contenant les caractères 'b','o','n','j','o','u','r',' \0'.

    Pour remplir un tableau de caractères, on peut utiliser différentes fonctions de la bibliothèque standard, comme scanf ou comme strcpy.

    ATTENTION.
    Si on écrit :

    char *chaine = "bonjour";
    ou bien
    char * chaine;
    puis plus loin l'instruction
    chaine = "bonjour";
    "bonjour" est une chaîne de caractères dite constante, dont l'adresse est donnée par la variable chaine. Il n'y a pas de véritable allocation-mémoire pour le contenu de cette chaîne. Il ne faudra alors pas chercher à modifier le mot bonjour (écrire chaine[1]='a'; serait incorrect). En revanche, chaine étant une variable, vous pouvez la modifier pour qu'elle contienne une autre adresse.

    Si on écrit :

    char chaine[10];
    l'instruction
    chaine = "bonjour";
    sera incorrect puisque chaine est une constante.

    Si on écrit :
    char * chaine;

    chaine=(char *) malloc(10 * sizeof(int));
    chaine="bonjour";
    tout est correct, mais chaine ne contient plus l'adresse du tableau que vous avez alloué dynamiquement, elle contient l'adresse de la chaîne constante de caractères "bonjour" (chaine[1]='a'; est incorrect...).

    Si vous voulez mettre "bonjour" dans le tableau alloué dynamiquement, il faut pour cela écrire :

    strcpy(chaine, "bonjour");
    à la place de
    chaine="bonjour";

     

    Commentaire d'un programme

    Une portion de texte comprise entre /* et */ signifie qu'il s'agit d'un commentaire.
    Un commentaire n'est pas pris en compte par le compilateur ; il sert à la lisibilité de votre programme.
    Grâce aux commmentaires, on peut expliquer au fur et à mesure du programme à quoi servent les variables et les fonctions utilisées.

     

    Constantes entières

    Il s'agit ici de définir une constante du programme, MAXDONNEES, qui est un majorant du nombre de données à trier. Pour faire cela, plusieurs méthodes sont envisageables.

    1) On peut utiliser la directive "#define" (qui s'adresse au préprocesseur, de même que "#include" que nous avons déjà vu). Lorsque l'on écrit :

    #define nom texte
    Chaque fois que le mot "nom" figure dans le programme, le préprocesseur le remplace par la suite de caractères de "texte".
    Par exemple :
    #define MAXDONNEES 8
    en début de programme aurait pour conséquence un remplacement systématique de la chaîne de caractères MAXDONNEES par 8. L'inconvénient serait de ne pas du tout "typer" MAXDONNEES : rien n'indique que MAXDONNEES représente un "int".
    Pour en savoir plus sur la directive
    #define.

    2) On peut utiliser la déclaration :

    const int MAXDONNEES=8;
    Bien qu'il soit alors interdit de changer la valeur de MAXDONNEES au cours du programme, le compilateur considère une variable déclarée "const" comme une variable. On ne pourra pas définir un tableau de longueur MAXDONNEES comme nous le faisons ici : pour définir le tableau tab, il est nécessaire que la taille du tableau ne soit pas une variable.

    3) Enfin, on peut utiliser une constante "énumérée" ; c'est ce que nous faisons ici ; retenez seulement pour l'instant que la déclaration

    enum {MAXDONNEES = 8};
    indique précisément que MAXDONNEES est une constante entière de valeur 8.

    Constantes énumérées

    On considère l'instruction :
    enum tour {R,V,B};
    On déclare ici des constantes entières : R, B, et V. Lorsque les valeurs des constantes ne sont pas indiquées, comme c'est le cas ici, leurs valeurs sont automatiquement mises à 0 pour la première, 1 pour la deuxième etc...

    Avec :

    enum bool(faux, vrai);
    faux vaut 0 et vrai vaut 1.

    On peut aussi préciser les valeurs des constantes ; par exemple, on peut écrire :

    enum notes {MIN = 4, MOYENNE = 12, MAX = 20};

    Si on écrit :

    enum semaine {lundi=1,mardi, mercredi, jeudi, vendredi, samedi, dimanche};
    lundi est une constante entière qui vaut 1, tandis que mardi vaut 2, ..., et dimanche vaut 7.

    On peut alors déclarer :

    enum bool verite;
    enum semaine un_jour;
    Certains disent alors que la variable verite est "du type" "enum bool" alors que un_jour serait "du type" "enum semaine". En fait, verite et un_jour ne sont rien d'autre que des variables de type "int", mais ce type de déclaration peut rendre le programme plus facile à lire.

     

    Conversion de type

    Une conversion de type suit la syntaxe :
    (nomDUnType)nomDUneVariable.
    Donnons un exemple d'utilisation de ce procédé. En C, la division entière se fait avec le symbole /. Si n et p sont deux variablesde type int qui valent respectivement 15 et 4, n/p vaut 3. Que faire si on veut faire une division non entière (pour obtenir ici 3,75) ? Sachant que / est aussi le symbole qui sert à faire une division ordinaire entre deux variables réelles (float ou double), il suffit de calculer
    (float)n/(float)p;
    On dit alors que l'on a effectué une conversion du type de n en le type float et de même pour p et la division est faite comme si on divisait un float par un float.

     

    Définition

    int i;
    déclare que le programme possède une variable appelée i qui est de type "int". Un emplacement en mémoire centrale est alloué pour cette variable. On dit aussi que la variable i est définie.
    Le mot "déclaration" fait référence à la description de type (ici on déclare que i est un "int"), le mot "définition" fait référence à l'allocation en mémoire faite pour la variable. Souvent, comme pour l'exemple ci-dessus, les deux opérations sont simultanées.
    L'emplacement en mémoire alloué pour une variable a une adresse. On obtient l'adresse d'une variable en faisant précéder son nom du symbole & (l'adresse de la variable i est &i...).

    Comme dans :

    int i, fact = 1;
    on peut définir consécutivement plusieurs variables ayant le même type. Les identificateurs des variables doivent être séparés par des virgules.

    On peut déclarer les variables :
    1) à l'extérieur de toute fonction : ce sont alors des variables globales ; les allocations en mémoire pour ces variables sont faites pour toute la durée du programme.
    2) à l'intérieur d'une fonction : ce sont alors des variables locales, qui sont allouées au moment du début de la fonction et libérées à la fin de la fonction. C'est le cas ici par rapport à la fonction main.

     

    En-tête d'une fonction

    L'en-tête d'une fonction est composé :
    • du type de la valeur retournée ou void si la fonction ne retourne rien
    • du nom de la fonction
    • entre parenthèses, de la liste des déclarations des paramètres séparés par des virgules ; si la fonction n'utilise aucun paramètre, on ne met rien entre les parenthèses.
    Exemples :
    • int lire()
      lire n'a aucun paramètre et retourne une valeur de type int.
    • void trier(int nombre)
      trier a un paramètre, nombre de type int, et ne retourne rien.
    • int effectuer(int n,int p,float x,int * tableau)
      La fonction effectuer retourne une valeur de type int, et possède 4 paramètres : n de type int, p de type int, x de type float et tableau qui est l'adresse d'un int.

     

    Fonction

    La définition d'une fonction est composée d'un en-tête et d'un corps.
    L'
    en-tête de la fonction permet d'indiquer si la fonction retourne une valeur et si elle admet des paramètres.
    Le corps d'une fonction est un bloc ; en particulier il commence par une accolade ouvrante({), peut avoir des déclarations de variables locales, puis une suite d'instructions, et se termine par une accolade fermante (}).
    L'instruction "return" fait sortir de la fonction ; le programme se poursuit alors avec l'instruction qui, dans la fonction appelante, suit l'appel à la fonction appelée. Si une fonction rend une valeur, celle-ci doit figurer après le mot "return" et avant le ";".

     

    Identificateurs

    Le langage C distingue les lettres minuscules des lettres majuscules.
    Les identificateurs sont constitués d'une lettre suivie d'une suite de caractères qui peuvent être des chiffres, des lettres ou le "trait bas" ("_").

     

    Incrémentation

    L'instruction i++; est synonyme de i=i+1; de même que l'instruction ++i;
    Il y a néanmoins une différence entre ++i et i++.
    Supposons que i vaille 2.
    Que fait tab[++i]=7; ?
    • On incrémente i de 1, qui vaut donc alors 3 ;
    • on met 7 dans tab[3] ;
    autrement dit, si ++ est devant i, la valeur de i est incrémentée avant que i ne soit utilisé.

    Que fait tab[i++]=7; (lorsque i vaut 2) ?
    • On met 7 dans tab[2] ;
    • on incrémente i de 1, qui vaut donc alors 3 ;
    autrement dit, si ++ est après i, la valeur de i est incrémentée après que i a été utilisé.

    On utilise aussi --i et i-- pour décrémenter;

     

    Définition

    Comme dans :
    int i, fact = 1;
    on peut définir consécutivement plusieurs variables ayant le même type. Les identificateurs des variables doivent être séparés par des virgules.

    Il reste possible d'initialiser les variables. Par exemple :

    int nombre=3, valeur, compteur=0;

    est valide.

     

    Listes chaînées

    Voir cet exemple.

     

    Macro

    On dit que l'on définit une macro quand on utilise la possibilité offerte par la directive #define

     

    Paramètre

    On appelle ainsi les variables qui sont indiquées dans l'en-tête d'une fonction.

    exemples : si une fonction a pour en-tête

    Les paramètres des fonctions sont exactement comme des variables locales que l'on peut initialiser au moment de l'appel de la fonction. Comme toute variable locale, elles disparaissent quand on quitte la fonction.

     

    Prototype

    Pour qu'une fonction puisse être appelée par une autre, il faut qu'elle soit "connue", c'est-à déclarée plus haut dans le fichier. Le prototype d'une fonction sert à cela.
    Le prototype d'une fonction est composée :
    • du type de la valeur retournée ou void si la fonction ne retourne rien
    • du nom de la fonction
    • entre parenthèses, de la liste des types des paramètres séparés par des virgules ; si la fonction n'admet aucun paramètre, on indique void entre les parenthèses. On peut indiquer après chaque type un nom de variable, mais celui-ci ne sera utile à rien.
    • un point-virgule.
    Exemple :
    int effectuer(int,int,float,int *);
    La fonction retourne une valeur de type int, et possède 4 paramètres de type successifs int, int, float et adresse d'un int.

    Lorsque le compilateur rencontre dans une instruction d'un programme l'appel d'une fonction, il vérifie si les types des arguments correspondent aux paramètres du prototype, sinon une erreur est détectée.
    Néanmoins, si une fonction est définie (i.e. écrite avec son en-tête et son corps) avant utilisation, il n'est pas né d'indiquer le prototype car l'en-tête de la fonction remplace le prototype.

     

    Raccourci d'affectation

    Quelques exemples pour effectuer deux opérations en une seule.
    • fact*=i; fait fact=fact*i;
      Elle multiplie donc fact par i puis met dans fact la valeur obtenue.
    • somme+=5; fait somme=somme+5;
    A vous d'imaginer d'autres exemples

     

    Recursivite

    Voir cet exemple.

     

    Les structures

    Une structure est un type composé de plusieurs variables de différents types ; ces variables sont les champs de la structure.
    Prenons l'exemple de la définition :
    struct eleve
    {
    char nom[20];
    char prenom[20];
    int note;
    };
    On définit ainsi un type dont le nom est struct eleve et dont les champs s'appellent nom, prenom et note.
    On peut alors définir une variable de type struct eleve comme suit :
    struct eleve unEleve;
    Alors :
  3. UnEleve.nom est un tableau de type char[20]
  4. UnEleve.prenom est un tableau de type char[20]
  5. UnEleve.note est une variable de type int.

    On aurait aussi pu grouper la définition du type struct eleve et de la variable unEleve avec :
    {

    char nom[20];
    char prenom[20];
    int note;
    } unEleve;

    Pour accéder au champ note de la variable unEleve, on écrit :

    unEleve.champ
    Il en va de même pour les autres champs.

    On peut faire des affectations entre structures du même type ; si on a :

    struct eleve unAutreEleve;
    on peut écrire :
    unAutreEleve = unEleve
    On peut aussi appliquer les opérateurs & et sizeof a une structure.

     

    Structure d'un programme


    Un programme en C est globalement structuré comme une collection de fonctions qui s'utilisent les unes les autres. Les différentes fonctions du programme communiquent soit en partageant des
    variables globales, soit par l'intermédiaire de valeurs retournées par les fonctions, soit par des passages de paramètres.
    Parmi les fonctions du programme, une et une seule doit être la fonction main.
    Une fonction ne peut pas contenir une fonction ; on n'a donc pas de structure emboîtée.

     

    Tableau

    La déclaration

    int tab[10]
    est celle d'un tableau "statique" destiné à contenir 10 variables de type int. La place nécessaire pour stocker un tel tableau est allouée dès la compilation : ceci exige bien entendu que la taille du tableau soit connue dès la compilation : ce sera soit une constante, soit une expression constante. Le type des éléments du tableau doit lui aussi être connu : il fait partie de la déclaration du tableau.

    ATTENTION : en C l'indice du premier élément d'un tableau est 0.

    On accède aux éléments du tableau "tab" par tab[0], tab[1], .... Le dernier élément du tableau tab est tab[9].

    L'identificateur tab n'est pas une variable ; c'est une constante dont la valeur est l'adresse de tab[0]. Il ne sera donc pas possible de faire figurer tab dans le premier membre d'une affectation.
    Les éléments du tableau sont rangés en mémoire de façon consécutive, de sorte que l'adresse du ième élément du tableau est une fonction simple de l'adresse du premier élément du tableau (c'est-à-dire tab) et de la taille nécessaire pour coder un élément du type des éléments rangés dans le tableau.

    Exemple :
    Considérons le programme suivant :
    void main()
    {
        int tab[10];
     
        printf("%d\n",sizeof(int));
        printf("%X\n",tab);
        printf("%X\n",&tab[1]);
        printf("%X\n",tab+1);
        printf("%X\n",&tab[3]);
    }
    "%X" est l'indicateur de format pour l'ériture d'un entier en octal.
    Vous pouvez consulter la fonction
    sizeof.
    On obtient à l'exécution :
    4
    EFFFF4D0
    EFFFF4D4
    EFFFF4D4
    EFFFF4DC

    Pour allouer un tableau dymamique, voir la fonction malloc.

     

    Tableau à plusieurs dimensions

    Voir cet exemple et celui-ci.

     

    Valeur d'une expression

    Toute expression en C a une valeur. Les valeurs des expressions servent essentiellement à effectuer des tests. Lorsqu'une expression a une valeur nulle, elle est considérée comme fausse et dans tous les autres cas, elle est considéré come vraie. Exemples :
    • 3 : valeur 3
    • 3==4 il s'agit du test d'égalité ; la valeur est 0 (i.e. faux)
    • 3=4 ; il s'agit d'une affectation ; la valeur prise est la valeur affecté, et donc 4.
    • 3<=4 ; cela vaut 1 (i.e. vrai).
    • x=y=7 :où x et y sont deux variables numériques ;'est plus compliqué ; c'est la même chose que x=(y=0) ; y=7 vaut 7, x vaut donc aussi 7 et l'expression vaut 7.

     

    Variable locale

    Lorsqu'une variable est déclarée dans un bloc B, elle est connue dans tout le bloc B, y compris dans les blocs internes à B, mais pas à l'extérieur de B.
    Des variables se trouvant dans des blocs disjoints peuvent porter le même nom.

     

    Variable globale

    Une variable globale est une variable déclarée à l'extérieur des fonctions. Une telle variable est connue par chaque fonction du programme qui n'utilise pas une variable locale du même nom.
    Irene Charon
    Last modified: Mon Sep 11 18:59:49 MET DST 2000