Réponses:
inline
indique au compilateur d' essayer d' 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 qui peuvent faire une grande différence de performances.
Cependant, ce n'est qu'un "indice", et le compilateur peut l'ignorer, et la plupart des compilateurs essaieront de "insérer" 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 serrée effectuera un appel de fonction à chaque itération, et le contenu de la fonction est en fait nettement inférieur au code que le compilateur doit mettre 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 */};
Sauter l'appel et le retour de la fonction réelle
Évidemment, c'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.
static
(avec ou sans inline
) peut être parfaitement bien dans l'en-tête, ne voyez aucune raison pourquoi pas. Les modèles sont pour C ++, cette question concerne C.
inline
est un bon style, imo
inline
ne pas donner des instructions au compilateur de faire toute tentative de inline. Il permet simplement au programmeur d'inclure le corps de la fonction dans plusieurs unités de traduction sans violation de l'ODR. Un effet secondaire de ceci est que cela permet au compilateur, quand il mettrait en ligne la fonction, de le faire.
Par défaut, une définition en ligne n'est valide que dans l'unité de traduction actuelle.
Si la classe de stockage est extern
, l'identificateur a une liaison externe et la définition en ligne fournit également la définition externe.
Si la classe de stockage est static
, l'identifiant a une liaison 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 actuelle, mais l'identifiant a toujours un lien 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 en ligne ou externe si la fonction est appelée dans l'unité de traduction actuelle.
Comme le compilateur est libre d'insérer (et non en ligne) 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 vraiment en compte that), dans la plupart des cas, il n'y a aucune différence entre les définitions de fonction static
et static inline
.
Le inline
spécificateur (comme la register
classe de stockage) n'est qu'un indice du compilateur, et le compilateur est libre de l'ignorer complètement. Les compilateurs non optimisés conformes aux normes n'ont qu'à honorer leurs effets secondaires, et les compilateurs d'optimisation feront ces optimisations avec ou sans conseils explicites.
inline
et register
ne sont pas inutiles, cependant, car ils demandent au compilateur de lancer des erreurs lorsque le programmeur écrit du code qui rendrait les optimisations impossibles: une inline
définition externe ne peut pas référencer des identifiants avec un lien 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 d'adresses de register
variables qualifiées.
Personnellement, j'utilise également la convention pour marquer static
les définitions de fonctions dans les en-têtes inline
, car la principale raison pour laquelle les définitions de fonctions sont placées dans les fichiers d'en-tête est de les rendre inlinables.
En général, je n'utilise que des définitions de static inline
fonction et d' static const
objet en plus des extern
déclarations dans les en-têtes.
Je n'ai jamais écrit de inline
fonction avec une classe de stockage différente de static
.
inline
comme si elle s'appliquait réellement à l'inlining est trompeuse et sans doute incorrecte. Aucun compilateur moderne ne l'utilise comme un indice pour l'inline ou l'exige afin d'activer l'inlining d'une fonction.
static
et static inline
. Les deux rendent la définition invisible aux autres unités de traduction. Alors, quelle serait une raison raisonnable d'écrire à la static inline
place static
?
D'après mon expérience avec GCC, je le sais static
et static inline
diffère en quelque sorte de la manière dont le compilateur émet des avertissements sur les fonctions inutilisées. Plus précisément, lorsque vous déclarez une static
fonction et qu'elle n'est pas utilisée dans l'unité de traduction actuelle, le compilateur produit un avertissement concernant une fonction inutilisée, mais vous pouvez empêcher cet avertissement en le changeant en static inline
.
Ainsi, j'ai tendance à penser que cela static
devrait être utilisé dans les unités de traduction et bénéficier d'un compilateur de vérification supplémentaire 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 lien externe) sans émettre d'avertissements.
Malheureusement, je ne trouve aucune preuve de cette logique. Même à partir de la documentation de GCC, je n'ai pas pu conclure que cela inline
inhibe les avertissements de fonction inutilisés. J'apprécierais si quelqu'un partageait des liens vers une description de cela.
warning: unused function 'function' [clang-diagnostic-unused-function]
pour une static inline
fonction lors de la construction avec clang-tidy
(v8.0.1), qui est utilisée dans une autre unité de traduction. Mais certainement, c'est l'une des meilleures explications et raison de combiner static
& inline
!
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
signifie la fonction en ligne qui ne peut être utilisée que dans ce fichier.
ÉDITER:
L'unité de compilation doit être l' unité de traduction
the compile unit
c'est quelque chose que j'ai écrit par erreur, il n'y a rien de tel, la terminologie réelle esttranslation unit
Une différence qui n'est pas au niveau du langage mais au niveau de l'implémentation populaire: certaines versions de gcc supprimeront les static inline
fonctions non référencées de la sortie par défaut, mais conserveront les static
fonctions simples 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 qu'il peut être judicieux de toujours utiliser inline
pour les static
fonctions dans les en-têtes.
inline
dans la définition? Voulez-vous également ne pas l'utiliser pour les extern
fonctions?
attribute((used))
et son utilisation pour permettre à asm de référencer des static
fonctions et des données autrement non référencées .
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.