On peut indiquer deux paramètres à la fonction main qui permettent d'indiquer au programme certaines valeurs au moment de l'exécution.
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 :
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 :
Si on écrit :
Si vous voulez mettre "bonjour" dans le tableau alloué dynamiquement, il faut pour cela écrire :
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 :
2) On peut utiliser la déclaration :
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
Avec :
On peut aussi préciser les valeurs des constantes ; par exemple, on peut
écrire :
Si on écrit :
On peut alors déclarer :
Comme dans :
On peut déclarer les variables :
Il reste possible d'initialiser les variables. Par exemple :
int nombre=3, valeur, compteur=0;
est valide.
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.
On aurait aussi pu grouper la définition du type struct eleve et de la variable unEleve avec :
Pour accéder au champ note de la variable unEleve, on écrit :
On peut faire des affectations entre structures du même type ; si on a :
La déclaration
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.
Exemple :
Pour allouer un tableau dymamique, voir la fonction malloc.
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 :
printf("bonjour");
l'argument est la chaîne de caractères "bonjour"
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
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 :
La variable lettre, de type char, est définie et initialisé avec le caractére a.
Conduit à l'écriture de '
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 :
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.
char chaine[]="bonjour";
chaine est alors un tableau de longueur 8 contenant les caractères
'b','o','n','j','o','u','r',' \0'.
Si on écrit :
ou bien
puis plus loin l'instruction
"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.
l'instruction
sera incorrect puisque chaine est une constante.
char * chaine;
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...).
à la place de
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
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 :
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.
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.
indique précisément que MAXDONNEES est une constante entière de valeur 8.
Constantes énumérées
On considère l'instruction :
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...
faux vaut 0 et vrai vaut 1.
lundi est une constante entière qui vaut 1, tandis que mardi vaut 2, ...,
et dimanche vaut 7.
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 :
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
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
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...).
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.
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é :
Exemples :
lire n'a aucun paramètre et retourne une valeur de type int.
trier a un paramètre, nombre de type int, et ne retourne rien.
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; ?
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) ?
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 :
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.
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
elle possède deux paramètres, les variables n et eleve. Il faudra l'appeler en lui indiquant deux arguments : un entier et une chaîne de caractères.
On pourra l'appeler par travaille(20,"Paul");
ou bien travaille(p,UnEleve); mais, dans ce second cas, il faut que p et UnEleve aient une valeur au moment de cette instruction.
int * étant le type utilisé pour des adresses de variables de type int, il faudra appeler cette fonction avec deux adresses de variable de type int.
Si a et b sont deux variables de type int, on pourra donc utiliser l'instruction :
echanger(&a, &b);
Ce deuxième exemple montre comment une fonction peut changer la valeur de variables de la fonction appelante, comme on peut le faire plus directement avec des langages permettant le passage des arguments par "adresses".
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 :
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.
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.
A vous d'imaginer d'autres exemples
Elle multiplie donc fact par i puis met dans fact la valeur obtenue.
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
{
};
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 :
Alors :
{
} unEleve;
Il en va de même pour les autres champs.
on peut écrire :
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
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.
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.
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
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 :
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