OMI à la fois rendre la fonction pour avoir une portée de l'unité de traduction uniquement.
Quelle est la différence entre les fonctions "statique" et "statique en ligne"?
Pourquoi inline
devrait-il être placé dans un fichier d’en-tête et non dans .c
fichier?
inline
indique au compilateur de tenter de incorporer le contenu de la fonction dans le code appelant au lieu d'exécuter un appel réel.
Pour les petites fonctions appelées fréquemment, cela peut faire une grande différence en termes de performances.
Cependant, il ne s'agit que d'un "indice" et le compilateur peut l'ignorer, et la plupart des compilateurs essaieront de "s'inscrire" même lorsque le mot clé n'est pas utilisé, dans le cadre des optimisations, lorsque 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 étroite effectuera un appel de fonction à chaque itération, et le contenu de la fonction est en réalité nettement inférieur au code que le compilateur doit mettre pour effectuer l'appel. inline
va essentiellement demander 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 de fonction et le retour
Évidemment, ceci est un exemple pour montrer le point, pas un vrai morceau de code.
static
fait référence à la portée. 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 en cours.
Si la classe de stockage est extern
, l'identifiant a un lien externe et la définition en ligne fournit également la définition externe.
Si la classe de stockage est static
, l'identifiant 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 une liaison externe et une définition externe doit être fournie dans une unité de traduction différente. Le compilateur est libre d'utiliser la définition inline ou externe si la fonction est appelée dans l'unité de traduction en cours.
Comme le compilateur est libre d’inscrire inline (et de ne pas inline) toute fonction dont la définition est visible dans l’unité de traduction actuelle (et, grâce aux optimisations de temps de liaison, même dans différentes unités de traduction, bien que le standard C ne prenne pas en compte cela), dans la plupart des cas, il n'y a pas de différence entre static
et static inline
définitions de fonctions.
Le spécificateur inline
(comme la classe de stockage register
) n'est qu'un indicateur du compilateur, et le compilateur est libre de l'ignorer complètement. Les compilateurs non optimisateurs conformes aux normes doivent uniquement prendre en compte leurs effets secondaires, et l'optimisation des compilateurs effectuera ces optimisations avec ou sans conseils explicites.
inline
et register
ne sont toutefois pas inutiles, car ils ordonnent au compilateur de générer des erreurs lorsque le programmeur écrit un code rendant les optimisations impossibles: Une définition externe inline
peut ' t identifiants de référence avec liaison interne (car ils ne seraient pas disponibles dans une unité de traduction différente) ou définissez des variables locales modifiables avec une durée de stockage statique (car elles ne partageraient pas l’état entre les unités de traduction), et vous ne pouvez pas prendre les adresses de register
- variables qualifiées.
Personnellement, j’utilise la convention pour marquer static
les définitions de fonctions dans les en-têtes ainsi que inline
, car la raison principale pour insérer des définitions de fonctions dans des fichiers d’en-tête est de les rendre inlinables.
En général, je n'utilise que static inline
fonction et static const
définitions d'objet en plus de extern
déclarations dans les en-têtes.
Je n'ai jamais écrit de fonction inline
avec une classe de stockage différente de static
.
D'après mon expérience avec GCC, je sais que static
et static inline
diffère en quelque sorte que le compilateur envoie des avertissements sur les fonctions inutilisées. Plus précisément, lorsque vous déclarez la fonction static
et qu’elle n’est pas utilisée dans l’unité de traduction actuelle, le compilateur génère un avertissement concernant la fonction inutilisée, mais vous pouvez empêcher cet avertissement en le modifiant en static inline
.
Ainsi, j'ai tendance à penser que static
devrait être utilisé dans les unités de traduction et tirer parti des possibilités supplémentaires du compilateur de chèques pour trouver des fonctions inutilisées. Et static inline
devrait être utilisé dans les fichiers d’en-tête pour fournir des fonctions qui peuvent être alignées (en raison de l’absence de liaison externe) sans émettre d’avertissements.
Malheureusement, je ne trouve aucune preuve de cette logique. Même dans la documentation de GCC, je n’ai pas pu conclure que inline
inhibe les avertissements de fonction inutilisés. J'apprécierais que quelqu'un partage des liens vers une description de cela.
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)
Alors, static inline
désigne la fonction en ligne utilisable uniquement dans ce fichier.
EDIT:
L'unité de compilation doit être L'unité de traduction
Une différence n’est pas au niveau de la langue mais au niveau de l’implémentation populaire: certaines versions de gcc supprimeront par défaut les fonctions static inline
Non référencées, mais conserveront les fonctions simples static
même si elles ne sont pas référencées. Je ne sais pas à quelles versions cela s'applique, mais d'un point de vue pratique, cela signifie que ce peut être une bonne idée de toujours utiliser inline
pour les fonctions static
dans les en-têtes.