- 11/04/2016
- 3 minutes à lire
-
- c
- v
- . n
- M
- g
-
+1
Une déclaration de fonction précède la définition de la fonction et en précise le nom, le type de retour, la classe de stockage et d’autres attributs d’une fonction. Pour être un prototype, la déclaration de fonction doit également établir les types et les identifiants des arguments de la fonction.
Syntaxe
déclaration:
spécifications de déclaration attribut-seqopt init-declarator-listopt ;
/* attribut-seqopt est spécifique à Microsoft */
spécifications de déclaration :
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
init-declarator-list :
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
declarator:
pointeropt direct-declarator
direct-declarator : /* Un déclarateur de fonction */
direct-declarator ( parameter-type-list ) /* Déclarateur de style nouveau */
direct-declarator ( identifier-listopt ) /* Déclarateur de style obsolète */
Le prototype a la même forme que la définition de fonction, sauf qu’il est terminé par un point-virgule immédiatement après la parenthèse fermante et n’a donc pas de corps. Dans les deux cas, le type de retour doit correspondre au type de retour spécifié dans la définition de la fonction.
Les prototypes de fonction ont les utilisations importantes suivantes :
-
Ils établissent le type de retour pour les fonctions qui retournent des types autres que
int
. Bien que les fonctions qui renvoient des valeursint
ne nécessitent pas de prototypes, les prototypes sont recommandés. -
Sans prototypes complets, les conversions standard sont effectuées, mais aucune tentative n’est faite pour vérifier le type ou le nombre d’arguments avec le nombre de paramètres.
-
Les prototypes sont utilisés pour initialiser les pointeurs vers les fonctions avant que ces fonctions ne soient définies.
-
La liste des paramètres est utilisée pour vérifier la correspondance des arguments de l’appel de fonction avec les paramètres de la définition de la fonction.
Le type converti de chaque paramètre détermine l’interprétation des arguments que l’appel de fonction place sur la pile. Une inadéquation de type entre un argument et un paramètre peut entraîner une mauvaise interprétation des arguments sur la pile. Par exemple, sur un ordinateur 16 bits, si un pointeur de 16 bits est transmis comme argument, puis déclaré comme paramètre long
, les 32 premiers bits de la pile sont interprétés comme un paramètre long
. Cette erreur crée des problèmes non seulement avec le paramètre long
, mais aussi avec tous les paramètres qui le suivent. Vous pouvez détecter les erreurs de ce type en déclarant des prototypes de fonction complets pour toutes les fonctions.
Un prototype établit les attributs d’une fonction de sorte que les appels à la fonction qui précèdent sa définition (ou se produisent dans d’autres fichiers source) peuvent être vérifiés pour les incompatibilités de type d’argument et de type de retour. Par exemple, si vous spécifiez le spécificateur de classe de stockage static
dans un prototype, vous devez également spécifier la classe de stockage static
dans la définition de la fonction.
Les déclarations complètes de paramètres (int a
) peuvent être mélangées avec des déclarateurs abstraits (int
) dans la même déclaration. Par exemple, la déclaration suivante est légale:
int add( int a, int );
Le prototype peut inclure à la fois le type de, et un identifiant pour, chaque expression qui est passée comme argument. Toutefois, ces identificateurs n’ont de portée que jusqu’à la fin de la déclaration. Le prototype peut également refléter le fait que le nombre d’arguments est variable, ou qu’aucun argument n’est passé. Sans une telle liste, les incompatibilités peuvent ne pas être révélées, et le compilateur ne peut donc pas générer de messages de diagnostic à leur sujet. Voir Arguments pour plus d’informations sur la vérification de type.
La portée du prototype dans le compilateur Microsoft C est maintenant conforme à ANSI lors de la compilation avec l’option de compilation /Za. Cela signifie que si vous déclarez une balise struct
ou union
dans un prototype, la balise est saisie à cette portée plutôt qu’à la portée globale. Par exemple, lors de la compilation avec /Za pour la conformité ANSI, vous ne pouvez jamais appeler cette fonction sans obtenir une erreur de correspondance de type :
void func1( struct S * );
Pour corriger votre code, définissez ou déclarez la struct
ou union
à la portée globale avant le prototype de fonction :
struct S;void func1( struct S * );
Sous /Ze, la balise est toujours entrée à la portée globale.
Voir aussi
Fonctions
.