Chapitre suivantIndex des CoursChapitre précedentChapitre 6

LES FONCTIONS

 

Objectifs

•  Comprendre la notion de fonction en C

•  Connaître les arguments d’une fonction

•  Connaître la notion de prototype en C

•  Différencier entre les variables globales et les variables locales

•  Comprendre la notion de transmission d’arguments entre fonctions

•  Connaître les classes d’allocation des variables

•Définir la portée d’une variable

Eléments de contenu

•  La notion de fonction en C

•  Exemple de fonction en C

•  Les arguments d’une fonction

•  Les fonctions fournissant un résultat

•  Les prototypes et le type void

•  Les arguments sont transmis par valeurs

•  Les variables globales

•  Les variables locales

•  La compilation séparée et ses conséquences

•  Les classes d’allocation des variables- leur portée et leur initialisation

Comme tous les langages, C permet de découper un programmes en plusieurs parties nommées souvent “modules”. Cette programmation dite “modulaire’’ se justifie pour plusieurs raisons:

•  Un programme écrit en un seul module devient difficile à comprendre dès qu’il dépasse une ou deux pages de texte. Une écriture modulaire permet de le diviser en plusieurs parties. Chacune de Ces parties peut d’ailleurs, si nécessaire, être décomposée à son tour en des modules plus élémentaires; Ce processus de décomposition pouvant être répété autant de fois que nécessaire comme le préconisent les méthodes de programmation structurée.

•     La programmation modulaire permet d’éviter des séquences d’instructions répétitives, et ceci d’autant plus que la notion “d’argument” permet de “paramétrer” certains modules.

•     La programmation structurée permet le partage d’outils communs qu’il suffit d’avoir écrit et mis au point une seule fois. Cet aspect sera plus visible grâce â la possibilité de compilation séparée offerte par le langage C.

I-LA NOTION DE FONCTION EN C

Dans beaucoup de langages, on trouve deux sortes de modules :

•     Les “fonctions”, assez proches de la notion mathématique correspondante. Notamment, une fonction dispose d’arguments qui correspondent à des informations qui lui sont transmises et elle fournit un unique résultat scalaire simple désigné parle nom même de la fonction, ce dernier peut apparaître dans une expression.

•     Les “procédures” (terme Pascal) ou “sous-programme” qui élargissent la notion de fonction. La procédure ne possède pas de valeur et son appel ne peut pas apparaître au sein d’une expression quelconque. Par contre, elle dispose d’argument. Parmi ces derniers certains peuvent, comme pour la fonction, correspondre à des informations qui lui sont transmises. Mais d’autres, contrairement à ce qui se passe pour les fonction correspondent à des informations qu’elle produit en retour de son appel.

En C, il n’existe qu’une seule sorte de module: la fonction. On l’utilise à la manière de la fonction mathématique, en faisant suivre son nom d’une liste d’arguments; le tout possède une valeur et peut donc apparaître dans une expression quelconque. Mais cette valeur peut ne pas être utilisée ; c’est ce qui se passe fréquemment lorsque vous utilisez printf ou scanf.

D’autre part, en C, une fonction peut modifier certains de ses arguments et donc fournir des informations en retour. Ainsi, malgré son nom, en C, la fonction peut jouer un rôle aussi général que la procédure ou le sous-programme d’autres langages.

Par ailleurs, nous verrons qu’en C plusieurs fonctions peuvent partager des informations autrement que par passage d’arguments, Nous retrouverons la notion classique de “variable globale”.

Il- EXEMPLE DE FONCTION EN C

Voici un exemple très simple de définition et d’utilisation de fonction en C

nain()

{

            ptimiste ()                                                                    il fait beau

}

     optimiste()

{

printif (Il fait  beau);

}

Nous y trouvons tout d’abord un programme principal formé d’un bloc (limité ici à une seule instruction). Mais cette fois à sa suite apparaît la définition d’une fonction. Celle-ci comporte :

•  un “en-tête“ qui précise le nom de la fonction (ici optimiste). Bien que cette fonction ne comporte aucun argument, les parenthèses qui suivent son nom sont obligatoires (comme elles l’étaient pour le nom main). Notez bien qu’un point-virgule n’apparaît pas à la fin de l’en-tête.

• un “corps” matérialisé par un bloc dans Lequel se trouvent les instruction que l’on souhaite voir exécutées par la fonction lorsqu’elle sera “appelée”

Ici, nous avons placé la fonction à la suite du programme principal, mais nous aurions pu la placer avant.

D’autre part, il faut noter que les fonctions sont toujours indépendantes les unes des autres. Aucune fonction ne peut être contenue dans une autre.

Au sein du programme principal, nous trouvons l’appel de la fonction. Il se fait par son nom suivi d’une paire de parenthèses obligatoires (même lorsque la fonction ne comporte aucun argument).

Vous voyez que le programme principal apparaît finalement comme une fonction de nom (main) imposé. La seule différence est que, par convention, l’exécution d’un programme commence toujours par cette fonction nommée main. Cette dernière n’est donc exécutée qu’une seule fois, alors que les autres fonctions peuvent l’être un nombre quelconque de fois.

III- LES ARGUMENTS D’UNE FONCTION

Soit l’exemple suivant :

main ()

{

int a =10, b=20;

     ecris(a) ;                                                                             valeur: 10
     ecris(b) ;                                                                             valeur: 20
     ecris(a+b) ;                                                                        valeur: .30

}

     ecris( int n)

{

printf (“valeur :%d\n“ ,n) ;

}

Dans la définition de la fonction ecris, nous trouvons l’en-tête :

ecris(int .n)

Cette fois, en pLus du nom de la fonction, nous y trouvons une indication signifiant que cette fonction possède un argument de type int nommé n. Cela signifie que lorsque cette fonction sera appelée, on lui transmettra une valeur de type int. Quant à l’usage que ecris doit faire de cette valeur, celui-ci lui est spécifié au sein des instructions du corps de la fonction, sachant que c est l’identificateur n qui désigne la valeur en question.

Le symbole n n’a de signification qu’au sein de la fonction ecris et il n’a aucun rapport avec d’éventuelles variables de même nom qui pourraient être définis en dehors. On dit souvent que n est un argument muet ou encore un argument formel.

Eu ce qui concerne l’utilisation de notre fonction ecris dans le programme principal, vous constatez que nous faisons suivre son nom d’une expression de type int, placée entre parenthèses. Cette expression porte je nom d’argument effectif .C’est sa valeur qui sera effectivement transmise à la fonction lors de l’appel.

En C, un argument effectif porte la forme de n’importe quelle expression. Au contraire un argument muet ne peut être qu’un identificateur de variable

D’une façon générale, une fonction peut avoir plusieurs arguments séparés par des virgules. Voici un exemple incomplet de définition et d’utilisation d’une fonction nommée fct possédant trois arguments.

main

{

int n, p ;

double x,y;

fct (n, p,x) ;

fct (n+p, 5 *n,x-y);

}

 fct (int i, int j, double v)

{

}

Dans ce cas, la correspondance entre argument effectifs et argument formels se fait en fonction de leur ordre d’apparition dans la liste.

Remarque:

Dans le C tel qu’il est défini par K&R, la déclaration de notre fonction ecris se présente de la façon suivante :

ecris (n)

int n ;

{

    …

}

L’entête est découpée en deux parties :

•     une première ligne précisant le nom de la fonction et la liste des arguments formels.

•     une suite de déclarations précisant les types des arguments.

IV- LES FONCTIONS FOURNISSANT UN RESULTAT

IV .1 Exemple de fonction calculant la somme de deux valeurs

soit cet exemple :

main()

{

int a, b, c, d, x, y;

     int som() ;                                                        

     a=1; b=2; c=S; d=4;

     x = som(a,b)+ ;                                                                  x=8
     printf( “r
= %d\n”,x);                                                        y = 21
     y
= 3*som(c,d) ;

printf( “y =%d\n“,y) ;

}

int som (int u,int vi)

{

int s;

s = u+v

return(s)

}

L’entête de la fonction précise toujours la liste des arguments formels avec leurs types ; mais de plus, ici, on y trouve (au début) l’indication du type du résultat que fournira la fonction.

Par ailleurs, dans le corps de la fonction on trouve une instruction :

return (s);

qui spécifie le résultat qui sera fournit par la fonction lors de son appel.

L’utilisation de la fonction som au sein du programme se fait toujours en faisant suivre son nom d’une liste d’arguments effectifs (ici deux arguments), comme par exemple :

som (a,b)

Comme la fonction fournit un résultat, une telle notation désigne effectivement une expression  qu’il est possible de l’utiliser à son tour dans une expression plus complète, comme nous l’avons fait dans l’expression :

x=  som (a, b) + 5;

De plus vous constatez la présence dans le programme principal d’une déclaration supplémentaire :

int som();

Cette déclaration précise au compilateur que som est une fonction et qu’elle fournit un résultat de type int. Nous reviendrons en détail sur la justification de cette déclaration dans la suite de cette leçon.

IV.2 L’instruction  return

D’une manière générale :

• L’instruction return peut mentionner n’importe quelle expression. Ainsi nous aurions pu écrire la fonction précédente d’une manière plus simple :

int som (int x, int y)

            {                                                                
               return (u+v);
           
}

• L’instruction returnpeut apparaître à plusieurs reprises dans une fonction, comme dans cet exemple :

double absom(double u, double v) // va leur absolue de la somme

{

double s;

s = a +b;

if (s> 0)

return (s),

else

return (-s);

}

il faut noter que non seulement l’instruction return définit la valeur du résultat, mais en même temps elle interrompt l’exécution de la fonction en revenant à la fonction (y compris la fonction principale main)qui l’a appelée. En l’absence de l’instruction return ce retour est mis en place automatiquement par le compilateur à la fin de la fonction.

 

IV.3 Quand on ne déclare pas le type du résultat

Dans notre exemple du paragraphe “fonctions fournissant un résultat”, nous avons placé, dans le programme principal, une déclaration précisant le type de la fonction som.On se demande pourquoi, puisque la définition de cette même fonction sont figure dans le même ficher source. En fait, il faut savoir que le compilateur travaille d’une manière relativement séquentielle. Plus précisément, vous ne pouvez pas faire référence à “quelque chose qui n’est définie que plus tard dans le source. C’est pourquoi la déclaration en question est indispensable ici.

Par contre, si, comme l’autorise C, vous aviez placé la définition de la fonction avant programme principal, vous auriez pu omettre cette déclaration; en effet le compilateur aura disposé de l’information de type de la fonction som.

Dune manière générale lorsque le compilateur rencontre l’appel d’une fonction, deux cas peuvent se présenter :

•     Il connaît le type de la fonction, soit parce qu’il la déjà compilé au sein du même source, soit qu’il existe une déclaration appropriée. Aucun problème particulier ne se pose alors.

•     Il ne connaît pas le type de la fonction. Dans ce cas il ne fournit pas de message d’erreur ; se contente de lui attribuer, par défaut, le type int.

Cette dernière particularité peut être gênante lorsque la fonction se trouve fournie ultérieurement avec un type différent de int. En effet le compilateur découvrira une incohérence entre le type qu’il avait attribué par défaut et le type effectif déclaré dans l’en-tête de la fonction.

V- LES PROTOTYPES ET LE TYPE VOID

V.1 Notion de prototype

Nous venons -de voir comment déclarer le type du résultat d’une fonction dans les modules on est amené à les utiliser. Le langage C autorise la déclaration d’un en-tête de fonction complet nommé “prototype’’ et qui fournit les types des paramètres.

Ainsi, dans notre précédent programme du paragraphe “Fonctions fournissant un résultat”, déclaration :

Int som() ;

du programme principal pourrait être remplacée par :

int som(int ,int) ;

ou encore par:

int som(int x, int y);

Dans le deuxième cas les paramètres x et y sont des paramètres fictifs.

V.2 Le râle du prototype                             

Si le prototype et l’en-tête sont compilés en même temps (c’est à dire qu’ils figurent dans le

même source), Le compilateur déclarera les incompatibilités entre les deux. Par contre; dans le cas où ils sont compilés séparément, aucune vérification n’est possible.

Dans tous les cas, le prototype sera utilisé pour forcer certaines conversions. Ainsi, si dans ni module, on a placé les déclarations :

double som, (double x1, double x2)

int n, p ;

et qu’on trouve un appel de la fonction som

som (n,p);

Le compilateur mettra en place une conversion des valeurs de n et p en valeurs de type double avant de les transmettre à la fonction som.

En l’absence de prototype, les valeurs des arguments effectifs sont soumises au règles de conversions en vigueur pour les expressions.

V.3 Les fichiers de type H

Les fichiers d’extension “.H” sont des fichiers qui correspondent chacun à une classe de fonctions. On y trouve entre autres chose des prototypes de ces fonctions. Ceci est très utile :

•    d’une part pour effectuer des contrôles sur le nombre et le type des arguments mentionnés dans les appels de ces fonctions,

•    d’autre part pour forcer d’éventuelles conversions auxquelles on risque de ne pas penser.

Pour utiliser ces fonctions dans vos programmes, il faut placer au début de vos sources une directives de genre :

#include <nomfichier.h>

Ainsi, pour utiliser la fonction mathématique sqrt() (qui calcule la racine carré d’un nombre), on doit mettre, au début du programme source la directive :

#mnclude <math.h>

Le fichier math.h contient les prototypes des fonctions mathématiques.

V.4 Le type void

Il sert à spécifier qu’une fonction ne retourne pas de résultat. Il peut s’employer aussi bien dans l’en-tête que dans le prototype. Ainsi on peut écrire :

void optimiste()

ou aussi

void ecrit (int n)

VI- LES ARGUMENT SONT TRANSMIS PAR VALEURS

Soit l’exemple suivant :

Main()

{

int n =10, p =20;

                                                                                                avant appel                  :10 20

                                                                                                                                                       
printf (“avant appel                    :%d %d\n“,n,p) ;                 début échange              :10 20
                                                                                                                                                       
  echange (n,p) ;                                                                     fin échange                   :20 10        
  printf (après appel                    : %d %d\n“,n,p) ;                après appel                   :10 20
}

echange (int a, int b)

{

int c ;

printif (“début échange            : %d %d\n“,a,b);

c=a ;

a=b ;

b=c ;

printf (“fin échange                  : %d %d\n“,a,b);

}

La fonction echange reçoit deux valeurs correspondant à ses deux arguments muets a et b. ELle effectue un échange de ces deux valeurs. Mais lorsque l’on est revenue dans le programme principal, aucune trace de cet échange ne subsiste sur les arguments effectifs n et p.

En effet, lors de l’appel de echange il y a eu transmission de la valeur des expressions n et p. On peut dire que ces valeurs on été recopiées “localement” dans la fonction echange dans des emplacements nommes a et b. C’est effectivement sur ses copies qu’a travaillé la fonction echange, de sorte que les valeurs des variables n et p n’ont pas été modifiés. C’est ce qui explique le résultat constaté.

Ce mode de transmission semble donc interdire à priori une fonction de produire une ou plusieurs valeurs ‘en retour’. Or, en C tous les “modules” doivent être écrits sous forme de fonctions. Ce problème d’échange des valeurs de deux variables doit pouvoir être résolue à l’aide d’une fonction.

Nous verrons que ce problème possède plusieurs solutions à savoir:

•      utiliser des variables “globales” comme nous le verrons

•      transmettre en argument la valeur de la dresse d’une variable. La fonction agira donc sur le contenu de cette adresse. C’est ce que nous verrons dans la leçon consacrée aux “pointeurs”.

VII- LES VARIABLES GLOBALES

En C, plusieurs fonctions (dont la fonction principale main) peuvent partager des variables communes qu’on qualifie alors de globales.

VII. 1 Exemple d’utilisation de variables globales

voyons cet exemple de programme:

int i;

main()

{                                                                                  Passage n0 I

     for( i=1; I<=5; i++)                                              Passage n02

            passage();                                                       Passage n° 3

}                                                                                  Passage n0 4
                                                                                    Passage n05

passage()

{

     printf (Passage n° %\n“,i);

}

La variable i a été déclarée en dehors de la fonction main. Elle est alors commune de toutes les fonctions qui seront compilées par la suite au sein du même source. Ainsi, ici, le programme principale affecte à i des valeurs qui se trouvent utilisées par la fonction passage().

VII.2 Les propriétés des variables globales

a)  portée

Les variables globales ainsi définies ne sont connues du compilateur que dans la partie du source suivant leur déclaration. On dit que leur “portée” (ou encore espace de validité) est limité à la partie du source qui suit leur déclaration.

Ainsi dans l’exemple suivant :

 nain()

{

             

}

int n ;

float x;

fct1(.)

{

             }

fct2(….)

{

            ….

}

Les variables n et x sont accessibles aux fonctions fct1 et fct2, mais pas au programme principal.

b)     Classe d’allocation

D’une manière générale, les variables globales existent pendant toute l’exécution du programme dans lequel elles apparaissent. Leurs emplacement mémoires sont complètement définis lors de l’édition des liens. On dit quelles font partie de la “classe d’allocation statique

De plus, Ces variables sont initialisées à zéro avant le début de l’exécution du programme, saut bien sûr, si vous les initialisez explicitement lors de leur déclaration.

VIII- LES VARIABLES LOCALES

Les variables définies au sein d’une fonction (qui peut être la fonction main) sont dites locales à la fonction dans laquelle elles sont déclarées.

VIII. 1 Portée des variables locales

Les variables locales ne sont connues qu’à l’intérieur des fonctions où elles sont déclarées. Leur portées est donc limitée à cette fonction.

Les variables locales n’ont aucun lien avec des variables globales de même nom ou avec d’autres variables locales à d’autres fonctions. Voyez cet exemple :

int n ;

            main()

{

           int p ;

}

            int n ;                                                          p
            float x ;
            fct(...)
           
{
            int n ;
             int
p;

            …

}

La variable p de main n’a aucun rapport avec la variable p de fct. De même, la variable n de fct n’a aucun rapport avec la variable globale n. Notez qu’il est impossible d’utiliser, dans la fonction fct, cette variable globale n.

VIII.2 Les variables locales automatiques

Par défaut, les variables locales ont une “durée de vie” limitée à celle d’une exécution de la fonction dans laquelle elles figurent.

Plus précisément, leurs emplacements ne sont pas définis de manière permanente comme ceux des variables globales un nouvel espace mémoire leur est alloué à chaque entrée dans la fonction et libéré à chaque sortie. Il sera donc généralement différent d’un appel à l’autre. On dit que la classe d’allocation de ces variables est automatique. Il faut souligner que : les valeurs des variables locales ne sont pas conservées d’un appel au suivant.

D’autre part, les valeurs transmises à une fonction sont traitées de la même manière que les variables locales. Leur durée de vie correspond également à celle de la fonction.

VIII.3 Les variables locales statiques

Il est toutefois possible d’attribuer un emplacement permanent à une variable locale et qu’ainsi sa valeur se conserve d’un appel au suivant. Il suffit pour cela de la déclarer à l’aide du mot-clé :

Static

En voici un exemple :

main()

{

       void fct();                                                                         appel n°1

int n ;                                                                                       appel n0 2

for( n=1 ; n<=5 ;n++)                                                           appel n0 3
                                                                                                appel n0 4

                                                                                                appel n0 5
 fct() ;          

                                                                                               
    {                                                                                         
 
                                                                                               

void fct()                                                                                 

{

static int i;

i++;

printf(“appel n° %d\n“ ,i) ;

}

La variable locale i a été déclarée de classe “statique”, On constate bien que sa valeur progresse de un à chaque appel. De plus on note qu’au premier appel sa valeur est nulle. En effet, comme pour les variables globales (lesquelles sont aussi de classe statique) :

 les variables locales de classe statique sont, par défaut initialisée à zéro.

Remarque:

Le mot staticemployé sans indication de type est équivalent à static int.

VIll.4Le cas des fonctions récursives

Le langage C autorise la récursivité des appel des fonctions. Celle-ci peut prendre deux aspects:

•     récursivité directe :une fonction comporte, dans sa définition, au mois un appel à elle même.

•     récursivité croisée : l’appel d’une fonction entraîne celui d’une autre fonction qui, à son tour appelle la fonction initiale ( on peut faire intervenir plus de deux fonctions).

Voici un exemple classique d’une fonction calculant le produit factoriel d’un nombre d’une manière récursive :

long fact (int n)

{

if(n > 1) return(fact( n - 1) * n);

e/se return(1) ;

}

Il faut bien voir qu’alors chaque appel de fact entraîne une allocation d’espace pour les éventuelles variables locales et pour son argument. Or, chaque nouvel appel de fact “à l’intérieur” de fact provoque une telle allocation sans que les emplacements précédents ne soient libérés. Il y a donc empilement des appels de la fonction. Ce n’est que lors de l’exécution de la première instruction return que l’on commence à ‘‘dépiler” les appels et les empLacements et donc à libérer de l’espace mémoire.

IX- LA COMPILATION SEPAREE ET SES CONSEQUENcES

C permet de compiler séparément plusieurs fichiers sources et de rassembler les modules objets correspondants au moment de l’édition des liens.

IX.1 La portée d’une variable globale - la déclaration extern

A priori, la portée d’une variable globale semble limitée au fichier source dans lequel elle a été définie. Ainsi, supposez que l’on compile séparément ces deux fichiers sources

                         source I                                                          source 2

                         int x;                                                               fct2()
                         main()                                                             {

{                                                                                       ….

                                                                      }

        ….

                                                                                              
                        }                                                                      fct3()

                        fct()                                                                  {

                                                                                                                ….

                                                                                                 }

                        {

                             ….

}

A priori, il ne semble pas possible, dans les fonctions fct2 et fct3 de faire référence à la variable globale x déclarée dans le premier fichier source (alors qu’aucun problème ne se poserait si l’on réunissait ces deux fichiers sources en un seul, du moins si l’on prend soin de placer les instructions du second fichier à la suite de celles du premier).

En effet, le langage C prévoit une déclaration permettant de spécifier qu’une variable globale a déjà été déclarée dans un autre fichier source. Celle-ci se fait à l’aide du mot-clé extern.. Ainsi en faisant précéder notre second fichier source de la déclaration

                              extern int x;

 il devient possible de mentionner la variable globale x (déclarée dans le premier fichier source) dans les fonctions fct2 etfct3.

IX.2 Les variables globales et l’édition des liens

Supposons que nous avons compilé les deux fichiers sources précédents, après avoir introduit dans le second la déclaration extern dont nous avons parlé ; voyons alors comment l’éditeur de lien est en mesure de rassembler correctement les deux modules objets ainsi obtenus. En particulier, examinons comment il fait correspondre au symbole x du second fichier source l’adresse effective de la variable x définie dans le premier.

D’une part, après compilation du premier fichier source, on trouve dans le module objet correspondant, une indication associant le symbole x et son adresse dans le module objet. Autrement dit, contrairement à ce qui se passe pour les variables locales pour lesquelles ne subsiste aucune trace de nom après compilation, le nom des variables globales continue à exister dans les modules objets. On retrouve là un mécanisme analogue à ce qui se passe pour les noms de fonctions, lesquels doivent bien subsister pour que l’éditeur de lien soit en mesure de retrouver les modules objets correspondants.

D’autre part, après compilation du second fichier source, on trouve dans le module objet correspondant une indication mentionnant qu’une certaine variable de nom x provient de l’extérieur et qu’il faudra en fournir l’adresse effective.

Ce sera effectivement le rôle de l’éditeur de liens que de retrouver dans le premier module objet l’adresse effective de la variable x et de la reporter dans le second module objet.

X-  LES CLASSES D’ALLOCATION DES VARIABLES - LEUR PORTEE ET LEUR INITIALISATION

X.1  La portée des variables

On peut classer les variables en quatre catégories en fonction de leur portée (ou espace de validité).

a) Les variables globales

Elles sont accessibles depuis n’importe quel endroit du fichier source faisant suite à l’emplacement où elles ont été définies. Elles sont également accessible depuis un autre fichier source ou depuis une autre partie du fichier source qui précède l’endroit où elles sont définies, par l’intermédiaire de la déclaration extern.

b) Les variables globales cachées

Ce sont des variables globales faisant l’objet d’une déclaration static. Elles ne sont accessible que depuis le fichier source où elles ont été définies.

c)  Les variables locales à une fonction

N’oubliez pas que les variables locales au programme principal (main) entrent dans cette catégorie.

d)  Les variables locales à un bloc

Le langage C permet de déclarer des variables au début d’un bloc de la même façon qu’au début d’une fonction. Dans ce cas la portée de telles variables est limitée au bloc en question.

X.2 Les classes d’allocation des variables

Il est également possible de classer les variables en trois catégories en fonction de leur classe d’allocation

a) La classe stade

On trouve dans cette catégorie les variables globales et les variables locales faisant l’objet d’une déclaration static. Les emplacements mémoire correspondants sont alloués une fois pour toutes au moment de l’édition de lien.

b) La classe automatique

Par défaut les variables locales entrent dans cette catégorie. Les emplacements mémoire correspondants sont alloués à chaque entrée dans la fonction et ils sont libérés à chaque sortie.

c) La classe register

Toute variable entrant à priori dans la classe automatique peut être déclarée explicitement par le qualificatif register. Celui-ci demande au compilateur d’utiliser dans la mesure du possible, un registre pour y ranger la variable ceci peut amener quelques gains de temps d’exécution.

Cette possibilité ne peut s’appliquer qu’aux variables scalaires.

X3.Le cas des fonctions

La fonction est considérée par le langage C comme un “objet global”. c’est ce qui permet d’ailleurs à l’éditeur de lien d’effectuer correctement son travail. Il n’est pas nécessaire d’utiliser une déclaration extern pour les fonction définies dans un fichier source différent de celui où elles sont appelées.

X.4 Initialisation des variables

a)  Les variables de classe statique

Ces variables sont permanentes. Elles sont initialisées une seule fois avant le début de l’exécution du programme.

Elles peuvent être initialisées explicitement lors de leur déclaration. Les valeurs servant à cette initialisation ne peuvent être que des constantes. En l’absence d’initialisation explicite, Ces variables seront initialisées à’’zéro ’’.

b) Les variables de classe automatique

Ces variables ne sont pas initialisées par défaut. Par contre, comme les variables de classe statique, elles peuvent être initialisées explicitement lors de leur déclaration.

Chapitre précedentIndex des CoursChapitre suivant

Révisé le :23-Sep-2007| ©2007 www.technologuepro.com