- Variables locales et globales
- Fonctions ne renvoyant pas de valeurs
- Variables statiques
- À propos de la déclaration des prototypes
Depuis maintenant quelques temps, nous sommes capable d’utiliser des fonctions : printf, puts…
Mais avec le C, il est possible au programmeur de créer ses propres fonctions (à ce titre, main en est une).
Voici la syntaxe d’une déclaration de fonction :
type identificateur(type argument){
[instructions]
return [valeur];
}
identificateur est un identificateur valide, qui doit suivre les même régles que pour les variables.
Il s’agit du nom de la fonction qui sera utilisé pour l’appeler.
type (devant indentificateur et argument) represente le type de donnée
renvoyé par la fonction ou le type de l’argument à transmettre (int, double …).
return permet de sortir de la fonction. valeur, qui est situé juste est facultatif.
Si on l’omet, la fonction ne renvera pas de valeur (voir plus bas).
Donc, pour écrire une fonction qui calculera la surface d’un cercle, on poura écrire :
double Cercle(double Rayon){
double Surface = Rayon * Rayon * 3.14159;/* Calcul de la surface*/
return Surface;/* Renvoi de la valeur*/
}
On peut ensuite appeler cette fonction à partir de la fonction principale. Voici le programme au complet :
#include <stdio.h>
double Cercle(double Rayon){
double Surface = Rayon * Rayon * 3.14159;
return Surface;
}
int main(){
int Rayon = 50;
double Aire = Cercle(Rayon);
printf("L'aire d'un cercle de rayon %d est %f", Rayon, Aire);
return 0;
}
Comme ceci, tout va bien : ça fonctionne. Mais pour des raisons qui paraitrons plus claires par la suite, on préfere
souvent écrire les fonctions à la suite de la fonction main.
Mais dans ce cas, si on laisse notre programme dans cet état, une erreur se produira (vous pouvez essayer).
Il nous faudra alors déclarer préalablement le protoype da la fonction Cercle.
Le prototype d’une fonction n’est rien d’autre que la première ligne de cette fonction. Dans notre cas, ce sera :
double Cercle(double Rayon);
Pour l’instant, nous écrirons ce prototype dans la fonction main.
Notre programme devient donc :
#include <stdio.h>
int main(){
double Cercle(double Rayon);/* Déclaration du prototype*/
int Rayon = 50;
double Aire = Cercle(Rayon);
printf("L'aire d'un cercle de rayon %d est %f", Rayon, Aire);
return 0;
}
double Cercle(double Rayon){
double Surface = Rayon * Rayon * 3.14159;
return Surface;
}
Variables locales et globales
Pour l’instant, nous n’avons travaillé qu’avec des variables locales à une fonction. Une variable
locale est une variable qui est uniquement accessible dans le bloc où elle a été déclarée. Par exemple, la
variable Aire de la fonction main de notre exemple précédent n’est pas accessible
par la fonction Cercle.
En fait, cette rêgle peut être étendue non pas aux fonctions, mais aux blocs d’instructions. Un bloc d’instructions,
vous le savez, est délimité par des accolades ({ et }).
Soit le code suivant :
#include <stdio.h>
int main(){
{
int i=5;
}
printf("i vaut %d", i);/* ERREUR! Undefined symbol i */
return 0;
}
Ce code provoque une erreur : la variable i est locale au bloc d’instruction situé au dessus.
Elle n’est donc pas accessible à l’instruction printf qui est placé en dehors du bloc.
Le code suivant est par contre correct :
#include <stdio.h>
int main(){
{
int i=5;
printf("i vaut %d", i);
}
return 0;
}
De même que celui-ci :
#include <stdio.h>
int main(){
int i=5;
{
printf("i vaut %d", i);
}
return 0;
}
On remarque qu’une variable est accessible uniquement dans le bloc où elle est déclarée, mais aussi dans tout
les blocs située dans ce même bloc.
Question : et si dans notre dernier exemple, on avait déclaré une autre variable i dans le bloc
imbriqué, que se serait-il passé ?
Reponse : une variable déclarée dans un bloc imbriqué est toujours prioritaire.
Conséquences :
#include <stdio.h>
int main(){
int i=5;
{
int i=3;
printf("i vaut %d", i);/* Sortie -> 3*/
i++;/* i = 4*/
}
printf("i vaut %d", i);/* Sortie -> 5*/
return 0;
}
Donc, pour déclarer une variable qui sera globale (une variable est dite globale lorsqu’elle est accessible
par tous les blocs, sans exceptions, d’un programme), on la déclarera tout simplement en début de programme :
#include <stdio.h>
int Compteur=0;/* Compteur est une variable globale*/
int main(){
void Incremente(void);/* Déclaration du prototype de Incremente */
int i;
printf("Avant, Compteur = %d\n", Compteur);
for(i=0; i < 10; i++)
Incremente();
printf("Après, Compteur = %d", Compteur);
return 0;
}
void Incremente(void){
Compteur++;/* incrementation de la variable globale Compteur*/
}
Comme prévu, Compteur est bien accessible par la fonction Incremente.
Fonctions ne renvoyant pas de valeurs
Dans l'exemple précedent, nous avons fait intervenir un nouvel element : void.
void est en fait un type de données à part entière. L'aide en ligne de Turbo C nous dit : Empty
data type (Type de données vide).
Autrement dit, la fonction Incremente utilisée dans l'exemple ci-dessus ne renvera pas de valeur.
Le second void est situé entre les parenthèses de la fonction. Cela veut simplement dire que la
fonction ne prend pas d'arguments.
L'emploi de void est également possible avec les variables, mais cela conserne l'utilisation
des pointeurs que nous étudierons plus tard.
Variables statiques
Par défaut, une variable locale à un bloc perd sa valeur entre les differents appels de celui-ci :
#include <stdio.h>
void MaFonction(void);
int main(){
int i;
for(i=0; i < 10; i++)
MaFonction();
return 0;
}
void MaFonction(void){
int MaVariable=0;
MaVariable++;/* MaVariable = 0 + 1 = 1 */
printf("MaVariable = %d\n", MaVariable);/* Sortie -> toujours 1 */
}
On voit bien que, malgrès tout nos efforts en appelant MaFonction 10 fois, la variable MaVariable
vaut toujours 0 (enfin, 1).
Pour remedier à ce probleme, il suffit de rajouter le mot-clef static devant la déclaration de MaVariable.
La variable ne sera ainsi initialiser qu'une seule fois à 0, et conservera sa valeur entre les appels :
#include <stdio.h>
void MaFonction(void);
int main(){
int i;
for(i=0; i < 10; i++)
MaFonction();
return 0;
}
void MaFonction(void){
static int MaVariable=0;
MaVariable++;/* Incrementation */
printf("MaVariable = %d\n", MaVariable);/* Sortie -> MaVariable + 1 */
}
À propos de la déclaration des prototypes
La déclaration des prototypes suivent les même rêgles que pour la déclaration des variables.
Completons notre première exemple avec une fonction permettant de calculer le volume d'un cylindre. On écrira :
double Cylindre(double Rayon, double Hauteur){
double Aire = Cercle(Rayon);
double Volume = Aire * Hauteur;
return Volume;
}
Maintenant, insérons cette fonction dans notre programme. Cela donne :
#include <stdio.h>
int main(){
double Cylindre(double Rayon, double Hauteur);/* Déclaration de Cylindre */
int Rayon = 50;
int Hauteur = 100;
double Volume = Cylindre(Rayon, Hauteur);
printf("Le volume d'un cylindre de rayon %d et de hauteur %d est %f",
Rayon, Hauteur, Volume);
return 0;
}
double Cylindre(double Rayon, double Hauteur){
double Aire = Cercle(Rayon);
double Volume = Aire * Hauteur;
return Volume;
}
double Cercle(double Rayon){
double Surface = Rayon * Rayon * 3.14159;
return Surface;
}
Tel quel, ce code provoquera une erreur, car le prototype de la fonction Cercle n'est pas déclaré
lors de son appel dans la fonction Cylindre. On peut alors le déclarer dans la fonction Cylindre :
double Cylindre(double Rayon, double Hauteur){
double Cercle(double Rayon);/* Déclaration de Cercle*/
double Aire = Cercle(Rayon);
double Volume = Aire * Hauteur;
return Volume;
}
Mais ainsi, la fonction Cercle ne sera pas accessible dans la fonction main.
Pour schematiser, on pourai dire que la fonction Cercle est locale à la fonction Cylindre
(c'est un raccourci rapide).
Toujours d'un point de vue schematique, si on veut que la fonction Cercle soit accessbile partout dans
le programme, il suffit de la déclarer en début de celui ci, comme pour les variables globales :
#include <stdio.h>
double Cercle(double Rayon);/* Cercle est accessible partout dans
le programme*/
int main(){
double Cylindre(double Rayon, double Hauteur);
int Rayon = 50;
int Hauteur = 100;
double Volume = Cylindre(Rayon, Hauteur);
printf("Le volume d'un cylindre de rayon %d et de hauteur %d est %f",
Rayon, Hauteur, Volume);
return 0;
}
double Cylindre(double Rayon, double Hauteur){
double Aire = Cercle(Rayon);
double Volume = Aire * Hauteur;
return Volume;
}
double Cercle(double Rayon){
double Surface = Rayon * Rayon * 3.14159;
return Surface;
}