IMO permet à la fonction d’avoir une scope de l’unité de traduction uniquement.
Quelle est la différence entre la fonction “statique” et la fonction “statique en ligne“?
Pourquoi devrait-on placer en inline
dans un fichier d’en-tête, pas dans le fichier .c
?
inline
demande au compilateur d’ essayer d’ intégrer le contenu de la fonction dans le code d’appel au lieu d’exécuter un appel réel.
Pour les petites fonctions appelées fréquemment, cela peut faire une grande différence de performance.
Cependant, ceci n’est qu’un “indice”, et le compilateur peut l’ignorer, et la plupart des compilateurs essaieront de “se connecter” même lorsque le mot clé n’est pas utilisé, dans le cadre des optimisations, là où c’est possible.
par exemple:
static int Inc(int i) {return i+1}; .... // some code int i; .... // some more code for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
Cette boucle serrée effectuera un appel de fonction à chaque itération, et le contenu de la fonction est en réalité sensiblement inférieur au code que le compilateur doit mettre en place pour effectuer l'appel. inline
demandera essentiellement au compilateur de convertir le code ci-dessus en un équivalent de:
int i; .... for (i=0; i<999999; i = i+1) { /* do something here */};
Ignorer l'appel et le retour de la fonction réelle
Evidemment, ceci est un exemple pour montrer le point, pas un vrai morceau de code.
static
réfère à la scope. En C, cela signifie que la fonction / variable ne peut être utilisée que dans la même unité de traduction.
Par défaut, une définition en ligne est uniquement valide dans l’unité de traduction actuelle.
Si la classe de stockage est extern
, l’identificateur a un lien externe et la définition en ligne fournit également la définition externe.
Si la classe de stockage est static
, l’identificateur a un lien interne et la définition en ligne est invisible dans les autres unités de traduction.
Si la classe de stockage n’est pas spécifiée, la définition en ligne n’est visible que dans l’unité de traduction en cours, mais l’identificateur a toujours un lien externe et une définition externe doit être fournie dans une autre unité de traduction. Le compilateur est libre d’utiliser la définition inline ou external si la fonction est appelée dans l’unité de traduction actuelle.
Comme le compilateur est libre d’inclure (et de ne pas aligner) toute fonction dont la définition est visible dans l’unité de traduction en cours (et, grâce aux optimisations de temps de liaison, même dans différentes unités de traduction, le cela), pour des raisons pratiques, il n’y a pas de différence entre static
définitions de fonctions static
et static inline
.
Le spécificateur en inline
(comme la classe de stockage de register
) est uniquement un indice de compilation et le compilateur est libre de l’ignorer complètement. Les compilateurs non optimisés conformes aux normes doivent uniquement respecter leurs effets secondaires, et l’optimisation des compilateurs effectuera ces optimisations avec ou sans indications explicites.
inline
et register
ne sont cependant pas inutiles, car ils indiquent au compilateur de lancer des erreurs lorsque le programmeur écrit du code qui rendrait impossible l’optimisation: une définition inline
externe ne peut pas faire référence à des identificateurs avec un lien interne (ceux-ci ne unité de traduction) ou définir des variables locales modifiables avec une durée de stockage statique (car elles ne partageraient pas d’états entre unités de traduction), et vous ne pouvez pas prendre d’adresse de variables qualifiées par un register
.
Personnellement, j’utilise la convention pour marquer aussi static
définitions de fonctions static
dans les en-têtes, car la principale raison de placer des définitions de fonctions dans des fichiers d’en-tête est de les rendre inline.
En général, je n’utilise que static inline
définitions de fonctions static inline
et static const
en plus des déclarations extern
dans les en-têtes.
Je n’ai jamais écrit de fonction en inline
avec une classe de stockage différente de la static
.
D’après mon expérience avec GCC, je sais que static
static inline
static
et static inline
diffère de la façon dont le compilateur émet des avertissements sur les fonctions inutilisées. Plus précisément, lorsque vous déclarez static
fonction static
et qu’elle n’est pas utilisée dans l’unité de traduction en cours, le compilateur génère un avertissement sur la fonction inutilisée, mais vous pouvez empêcher cet avertissement en le transformant en static inline
.
Ainsi, j’ai tendance à penser que le static
devrait être utilisé dans les unités de traduction et bénéficier de vérifications supplémentaires que le compilateur fait pour trouver les fonctions inutilisées. Et static inline
devrait être utilisé dans les fichiers d’en-tête pour fournir des fonctions qui peuvent être intégrées (en raison de l’absence de liens externes) sans émettre d’avertissements.
Malheureusement, je ne trouve aucune preuve de cette logique. Même à partir de la documentation GCC, je n’ai pas pu conclure que l’ inline
inhibe les avertissements de fonction inutilisés. J’apprécierais si quelqu’un partagerait des liens à la description de cela.
Une différence qui n’est pas au niveau du langage mais au niveau d’implémentation populaire: certaines versions de gcc suppriment par défaut static inline
fonctions static inline
non référencées, mais conservent static
fonctions static
même si elles ne sont pas référencées. Je ne suis pas sûr de savoir à quelles versions cela s’applique, mais d’un sharepoint vue pratique, cela signifie qu’il peut être judicieux de toujours utiliser inline
pour static
fonctions static
dans les en-têtes.
En C, static
signifie que la fonction ou la variable que vous définissez ne peut être utilisée que dans ce fichier (c’est-à-dire l’unité de compilation)
Donc, static inline
signifie la fonction inline qui ne peut être utilisée que dans ce fichier.
MODIFIER:
L’unité de compilation devrait être The Translation Unit