6.7.4 Spécificateurs de fonction
Une nouvelle fonctionnalité de C99: Le inline
mot-clé, adapté de C ++, est un spécificateur de fonction qui ne peut être utilisé que dans les déclarations de fonction. Il est utile pour les optimisations de programme qui nécessitent la définition d'une fonction pour être visible sur le site d'un appel. (Notez que la norme ne tente pas de spécifier la nature de ces optimisations.)
La visibilité est assurée si la fonction a une liaison interne, ou si elle a une liaison externe et que l'appel est dans la même unité de traduction que la définition externe. Dans ces cas, la présence du inline
mot -
clé dans une déclaration ou une définition de la fonction n'a aucun effet au-delà de l'indication d'une préférence selon laquelle les appels de cette fonction devraient être optimisés de préférence aux appels d'autres fonctions déclarées sans le inline
mot - clé.
La visibilité est un problème pour un appel d'une fonction avec lien externe où l'appel est dans une unité de traduction différente de la définition de la fonction. Dans ce cas, le inline
mot - clé permet à l'unité de traduction contenant l'appel de contenir également une définition locale ou en ligne de la fonction.
Un programme peut contenir une unité de traduction avec une définition externe, une unité de traduction avec une définition en ligne et une unité de traduction avec une déclaration mais pas de définition pour une fonction. Les appels dans cette dernière unité de traduction utiliseront la définition externe comme d'habitude.
Une définition en ligne d'une fonction est considérée comme une définition différente de la définition externe. Si un appel à une fonction func
avec un lien externe se produit là où une définition en ligne est visible, le comportement est le même que si l'appel était fait à une autre fonction, par exemple
__func
, avec un lien interne. Un programme conforme ne doit pas dépendre de la fonction appelée. Il s'agit du modèle en ligne de la norme.
Un programme conforme ne doit pas s'appuyer sur l'implémentation utilisant la définition en ligne, ni sur l'implémentation utilisant la définition externe. L'adresse d'une fonction est toujours l'adresse correspondant à la définition externe, mais lorsque cette adresse est utilisée pour appeler la fonction, la définition en ligne peut être utilisée. Par conséquent, l'exemple suivant peut ne pas se comporter comme prévu.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr(); // unspecified behavior
}
Étant donné que l'implémentation peut utiliser la définition en ligne pour l'un des appels à saddr
et utiliser la définition externe pour l'autre, il n'est pas garanti que l'opération d'égalité s'évalue à 1 (vrai). Cela montre que les objets statiques définis dans la définition en ligne sont distincts de leur objet correspondant dans la définition externe. Cela a motivé la contrainte de ne même pas définir un non- const
objet de ce type.
L'inlining a été ajouté à la norme de manière à pouvoir être implémenté avec la technologie de l'éditeur de liens existante, et un sous-ensemble d'inlining C99 est compatible avec C ++. Ceci a été réalisé en exigeant qu'une seule unité de traduction contenant la définition d'une fonction en ligne soit spécifiée comme celle qui fournit la définition externe de la fonction. Comme cette spécification consiste simplement en une déclaration qui ne inline
contient pas le mot clé ou qui contient les deux inline
et extern
, elle sera également acceptée par un traducteur C ++.
L'intégration en C99 étend la spécification C ++ de deux manières. Premièrement, si une fonction est déclarée
inline
dans une unité de traduction, elle n'a pas besoin d'être déclarée inline
dans toutes les autres unités de traduction. Cela permet, par exemple, une fonction de bibliothèque qui doit être incorporée dans la bibliothèque mais disponible uniquement via une définition externe ailleurs. L'alternative d'utiliser une fonction wrapper pour la fonction externe nécessite un nom supplémentaire; et cela peut également avoir un impact négatif sur les performances si un traducteur ne fait pas réellement de substitution en ligne.
Deuxièmement, l'exigence que toutes les définitions d'une fonction en ligne soient «exactement les mêmes» est remplacée par l'exigence selon laquelle le comportement du programme ne doit pas dépendre du fait qu'un appel est implémenté avec une définition en ligne visible, ou la définition externe, d'un fonction. Cela permet à une définition en ligne d'être spécialisée pour son utilisation dans une unité de traduction particulière. Par exemple, la définition externe d'une fonction de bibliothèque peut inclure une validation d'argument qui n'est pas nécessaire pour les appels effectués à partir d'autres fonctions de la même bibliothèque. Ces extensions offrent certains avantages; et les programmeurs préoccupés par la compatibilité peuvent simplement se conformer aux règles plus strictes du C ++.
Notez qu'il n'est pas approprié pour les implémentations de fournir des définitions en ligne des fonctions de bibliothèque standard dans les en-têtes standard, car cela peut casser certains codes hérités qui redéclarent les fonctions de bibliothèque standard après avoir inclus leurs en-têtes. Le inline
mot-clé est uniquement destiné à fournir aux utilisateurs un moyen portable de suggérer l'intégration de fonctions. Étant donné que les en-têtes standard n'ont pas besoin d'être portables, les implémentations ont d'autres options telles que:
#define abs(x) __builtin_abs(x)
ou d'autres mécanismes non portables pour incorporer des fonctions de bibliothèque standard.