Namespaces
Variants

Function definitions

From cppreference.net

Une définition de fonction associe le corps de la fonction (une séquence de déclarations et d'instructions) au nom de la fonction et à la liste des paramètres. Contrairement à la déclaration de fonction , les définitions de fonctions sont autorisées uniquement au niveau de la portée du fichier (il n'existe pas de fonctions imbriquées).

C prend en charge deux formes différentes de définitions de fonctions :

attr-spec-seq (optionnel) specifiers-and-qualifiers parameter-list-declarator function-body (1)
specifiers-and-qualifiers identifier-list-declarator declaration-list function-body (2) (jusqu'en C23)

attr-spec-seq - (C23) une liste optionnelle d' attributs , appliquée à la fonction
specifiers-and-qualifiers - une combinaison de
parameter-list-declarator - un déclarateur pour un type de fonction qui utilise une liste de paramètres pour désigner les paramètres de la fonction
identifier-list-declarator - un déclarateur pour un type de fonction qui utilise une liste d'identifiants pour désigner les paramètres de la fonction
declaration-list - une séquence de déclarations qui déclare chaque identifiant dans identifier-list-declarator . Ces déclarations ne peuvent pas utiliser d'initialiseurs et le seul spécificateur de classe de stockage autorisé est register .
function-body - une instruction composée , c'est-à-dire une séquence d'instructions et de déclarations entre accolades, qui est exécutée chaque fois que cette fonction est appelée
1) Définition de fonction de style nouveau (C89). Cette définition introduit à la fois la fonction elle-même et sert de prototype de fonction pour toute future expression d'appel de fonction , forçant les conversions des expressions d'arguments vers les types de paramètres déclarés.
int max(int a, int b)
{
    return a>b?a:b;
}
double g(void)
{
    return 0.1;
}
2) (jusqu'à C23) Définition de fonction de style ancien (K&R). Cette définition ne se comporte pas comme un prototype et toute future expression d'appel de fonction effectuera des promotions d'arguments par défaut.
int max(a, b)
int a, b;
{
    return a>b?a:b;
}
double g()
{
    return 0.1;
}

Table des matières

Explication

Comme pour les déclarations de fonctions , le type de retour de la fonction, déterminé par le spécificateur de type dans specifiers-and-qualifiers et éventuellement modifié par le declarator comme d'habitude dans les déclarations , doit être un type d'objet complet non-tableau ou le type void . Si le type de retour serait qualifié cvr, il est ajusté vers sa version non qualifiée pour la construction du type de fonction.

void f(char *s) { puts(s); } // type de retour est void
int sum(int a, int b) { return a+b; } // type de retour est int
int (*foo(const void *p))[3] { // type de retour est pointeur vers un tableau de 3 int
    return malloc(sizeof(int[3]));
}

Comme pour les déclarations de fonctions , les types des paramètres sont ajustés des fonctions vers les pointeurs et des tableaux vers les pointeurs pour la construction du type de fonction, et les qualificatifs cvr de plus haut niveau de tous les types de paramètres sont ignorés pour déterminer le type de fonction compatible .

Contrairement aux déclarations de fonction , les paramètres formels anonymes ne sont pas autorisés (sinon, il y aurait des conflits dans les définitions de fonction de l'ancien style (K&R)), ils doivent être nommés même s'ils ne sont pas utilisés dans la fonction. La seule exception est la liste de paramètres spéciale ( void ) .

(jusqu'en C23)

Les paramètres formels peuvent être anonymes dans les définitions de fonction, car les définitions de fonction de l'ancien style (K&R) ont été supprimées. Les paramètres anonymes sont inaccessibles par nom dans le corps de la fonction.

(depuis C23)
int f(int, int); // déclaration
// int f(int, int) { return 7; } // Erreur jusqu'à C23, OK depuis C23
int f(int a, int b) { return 7; } // définition
int g(void) { return 8; } // OK : void ne déclare pas de paramètre

Dans le corps de la fonction, chaque paramètre nommé est une expression lvalue , ils ont une durée de stockage automatique et une portée de bloc . La disposition des paramètres en mémoire (ou s'ils sont stockés en mémoire) n'est pas spécifiée : cela fait partie de la convention d'appel .

int main(int ac, char **av)
{
    ac = 2; // les paramètres sont des lvalues
    av = (char *[]){"abc", "def", NULL};
    f(ac, av);
}

Voir l'opérateur d'appel de fonction pour plus de détails sur la mécanique d'un appel de fonction et return pour le retour depuis les fonctions.

__func__

Dans chaque corps de fonction , la variable prédéfinie spéciale __func__ avec portée de bloc et durée de stockage statique est disponible, comme si elle était définie immédiatement après l'accolade ouvrante par

static const char __func__[] = "function name";

Cet identifiant spécial est parfois utilisé en combinaison avec les constantes de macro prédéfinies __FILE__ et __LINE__ , par exemple, par assert .

(depuis C99)

Notes

La liste d'arguments doit être explicitement présente dans le déclarateur, elle ne peut pas être héritée d'un typedef

typedef int p(int q, int r); // p est un type de fonction int(int, int)
p f { return q + r; } // Erreur

En C89, specifiers-and-qualifiers était optionnel, et s'il était omis, le type de retour de la fonction par défaut était int (éventuellement modifié par le declarator ).

De plus, l'ancien style de définition ne nécessitait pas de déclaration pour chaque paramètre dans declaration-list . Tout paramètre dont la déclaration était manquante avait le type int

max(a, b) // a and b have type int, return type is int
{
    return a>b?a:b;
}
(jusqu'à C99)

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C publiées précédemment.

DR Appliqué à Comportement publié Comportement correct
DR 423 C89 le type de retour pourrait être qualifié le type de retour est implicitement déqualifié

Références

  • Norme C17 (ISO/CEI 9899:2018):
  • 6.9.1 Définitions de fonctions (p: 113-115)
  • Norme C11 (ISO/IEC 9899:2011):
  • 6.9.1 Définitions de fonctions (p: 156-158)
  • Norme C99 (ISO/IEC 9899:1999) :
  • 6.9.1 Définitions de fonctions (p: 141-143)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 3.7.1 Définitions de fonctions

Voir aussi

Documentation C++ pour Définition de fonction