IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Notes sur le langage C

Date de publication : 29 avril 2009


X. Le type retourné par main()
X-A. Historique
XI. C'est quoi un prototype ?
XII. Bibliothèques de fonctions
XII-A. Bibliothèque statique
XII-B. Bibliothèque dynamique
XIII. Pourquoi ma fonction ne modifie pas ma variable ?
XIV. Les fonctions à nombre d'arguments variable


X. Le type retourné par main()

Bien que main() soit censé retourner un int, on voit quelquefois écrit

void main (void)
{
}
Qu'en est-il exactement ?

D'après la définition du langage C, dans un programme conforme, main() doit retourner int. D'ailleurs un compilateur comme Borland C 3.1 en mode ANSI refuse void main() (error). Dans les mêmes conditions, gcc qui émet un avertissement (warning).


X-A. Historique

Dès l'apparition du langage C, une des formes canoniques de main() était

main()
{
   return 0;
}
l'autre étant la forme qui permet de récupérer les arguments de la ligne de commande.

Il faut bien comprendre qu'à cette époque, une fonction définie sans type de retour explicite, retournait un int (c'est toujours le cas en C90, mais plus en C99 où le type doit être explicite). Le mot clé 'void' n'existait pas.

info Il n'y avait donc aucune raison d'utiliser une forme void main().
Ensuite, est venue la normalisation du langage C. (1989 ANSI, 1990 ISO). Dans le texte, les deux formes canoniques sont décrites :

int main (void)
et

int main (int argc, char **argv)
Il est précisé en remarque (dans la partie non normative) qu'il existe d'autres formes sans autres précisions. Elles ne font donc pas partie de la norme, leur comportement est donc indéfini dans le cadre d'un programme respectueux de la norme (dit 'strictement conforme').


XI. C'est quoi un prototype ?

Lorsqu'on défini une fonction,

int f (char *s)
{
  ...
}
on définit en même temps son interface, à savoir :

  • son nom (ici , f)
  • son type de retour (ici, int)
  • ses paramètres (ici, s, de type pointeur sur char)
Cet interface est aussi appelé prototype intégré. Il permet une utilisation de la fonction si l'appel est placé après la définition (il n'y a pas de raison de faire autrement, sauf cas exceptionnels et souvent douteux...) :

int f (char *s)
{
  ...
}

int main (void)
{
   int x = f("hello");
}
Maintenant, dans le cas de compilation séparée, on doit 'détacher' le prototype et le placer dans un fichier qui sera inclus à la fois dans le fichier d'implémentation de la fonction et dans le ou les fichiers qui l'utilisent.

/* f.h */
int f (char *s);

/* f.c */
#include "f.h"
int f (char *s)
{
  ...
}

/* main.c */
#include "f.h"

int main (void)
{
   int x = f("hello");
}
Pour compléter, il est fortement recommandé de protéger les fichiers .h contre les inclusions multiples avec une garde (guard) :

#ifndef H_F
#define H_F
/* f.h */

int f (char *s);

#endif
Détails ici


XII. Bibliothèques de fonctions

Une bibliothèque (library) est une collection de fonctions mise à la disposition des programmeurs. Elle se compose d'une interface matérialisée par un ou plusieurs fichiers d'entêtes (.h), et d'un fichier d'implémentation qui contient le corps des fonctions (.lib, .a, .dll, .so etc.) sous forme exécutable.

Il est aussi possible à un programmeur de 'capitaliser' son travail en réalisant des fonctions réutilisables qu'il peut ensuite organiser en bibliothèques. Cette pratique est courante et encouragée. La création physique d'une bibliothèque est assez simple si on respecte quelques règles de conception, comme l'absence de globales, la souplesse et l'autonomie. Elle nécessite un outil spécialisé (librarian) généralement livré avec toute implémentation du langage C.

Une bibliothèque peut être statique ou dynamique (partagée).


XII-A. Bibliothèque statique

Une bibliothèque à édition de lien statique (.lib, .a etc.) est liée à l'application pour ne former qu'un seul exécutable. La taille de celui-ci peut être importante, mais il a l'avantage d'être autonome. Cette pratique a l'avantage de la simplicité, et elle ne requiert aucune action particulière de la part d'un éventuel système lors de l'exécution du programme. Elle est très utilisée en programmation embarquée (embedded).


XII-B. Bibliothèque dynamique

Une bibliothèque à édition de lien dynamique, est un fichier séparé (.dll, .so, ...) qui doit être livré avec l'exécutable. L'intérêt est que plusieurs applications peuvent se partager la même bibliothèque, ce qui est intéressant, surtout si sa taille est importante. Dans ce cas, les exécutables sont plus petits. Autre avantage, les défauts de la bibliothèque peuvent être corrigés indépendamment des applications. Ensuite, la correction est répercutée immédiatement sur toutes les applications concernées par simple mise à jour de la bibliothèque dynamique.

Une application qui utilise une bibliothèque dynamique doit réaliser le lien avec la bibliothèque à l'exécution. Pour cela, elle utilise des appels à des fonctions système spécifiques dans sa phase d'initialisation. Les détails dépendent de la plate-forme.


XIII. Pourquoi ma fonction ne modifie pas ma variable ?

Il y a deux façon de modifier la valeur d'un objet (aka variable) avec une fonction :

  • Récupérer la valeur retournée par la fonction :

int x = f();
ou

int x;
   x = f();
avec

int f(void);
  • Passer l'adresse de la variable dont on veut modifier la valeur à la fonction :

int x;
   f(&x);
avec

void f(int *);
Si l'objet est un pointeur, la règle est la même :

  • Retourner une valeur :

int *px = f();
avec

 int *f(void);
  • Passer l'adresse :

int *px;
   f(&px);
avec

void f(int **);
warning Il n'y a aucune chance de modifier l'entier en faisant ceci :

     int x;
   f(x);
warning De même, il n'y a aucune chance de modifier le pointeur en faisant cela :

 int *px;
   f(px);

XIV. Les fonctions à nombre d'arguments variable

 

Valid XHTML 1.1!Valid CSS!

Copyright © 2009 Emmanuel Delahaye. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.