Quand mettre statique des définitions de fonctions dans les fichiers d'en-tête dans le C?
J'ai trouver un code qui a une grande fonction statique dans un fichier d'en-tête et je suis juste curieux de savoir quand il est/n'est pas ok pour ce faire. Par exemple, si de nombreux .c
fichiers à inclure l'en-tête, pourquoi ne pas simplement définir la fonction non-statique et lien dans ?
Des conseils ou des règles de pouce quand/quand ne pas mettre statique des définitions de fonctions dans les fichiers d'en-tête dans le C serait appréciée,
grâce
- Je n'utilise que des fonctions statiques dans les fichiers d'en-tête pour une programmation simple des microcontrôleurs. Dans cet environnement, il y a juste le seul programme en cours d'exécution sur la puce (aucun système d'exploitation), et les fonctions incluses ont également tendance à être très simple, comme l'envoi de données sur le port série, par exemple. Je ne sais pas si c'est la bonne réponse (j'aimerais entendre certains commentaires, si ce n'), mais il simplifie les choses pour moi et je ne vois pas d'inconvénients pour cette application particulière.
Vous devez vous connecter pour publier un commentaire.
Quelques idées:
mylib123__foobar
, et#define foobar mylib123__foobar
dans le fichier d'en-tête, de sorte que celui-ci semble un peu suspecte.)Peut-être la fonction est simplement un wrapper pour une fonction externe, et de la façon dont l'emballage des œuvres dépend peut-être de compiler options au moment de l'appel de la unité de compilation. Par exemple:
Vous pourriez dire que juste l'utilisation de macros, mais que faire si
foobar
doit être appelé par l'intermédiaire d'un pointeur de fonction pour l'usage prévu?Avec cela dit...
En réalité, la principale raison les gens mettent
static
fonctions dans les fichiers d'en-tête est généralement basée sur quelques 10-ans-conception dépassée qu'elle permettra d'améliorer les performances, en permettant au compilateur de la fonction inline ou autres joyeusetés. La plupart des gens qui n'ont pas fait de mesure. Depuis les compilateurs modernes permet de compiler l'ensemble du programme en tant qu'unité si demandé, et ce, théoriquement, les résultats dans beaucoup plus de possibilités pour l'optimisation, et depuis il est discutable d'optimisation pour commencer, je suis vraiment sceptique sur le placement de fonctions de dans les en-têtes pour le calcul des performances.Cette critique s'applique en particulier le cas des OP exemple de "grandes" fonctions statiques dans les fichiers d'en-tête. Il n'y a presque aucun moyen d'une grande fonction, pourraient bénéficier de l'in-lining, à moins qu'une constante de la valeur de l'argument permet au compilateur d'éliminer 90% du code ou quelque chose. (Pour un exemple du monde réel de ce cas extrême, voir certains des fous de la fonction inline/macro définitions utilisées dans
libavcodec
. 🙂En règle générale, vous ne devez pas mettre des fonctions statiques dans les fichiers d'en-tête. Dans un programme, il ne sera probablement pas mal quoi que ce soit, en dehors de l'expansion de la taille de votre code parce que vous avez une copie redondante dans chaque module. Dans une bibliothèque partagée, il pourrait facilement provoquer des bugs, car maintenant partie de votre bibliothèque est intégrée à la bibliothèque de l'appelants, de sorte que les différences de version pourrait facilement se produire.
Si vous avez de l'terriblement, terriblement temps-fonction critique où le temps passé à faire l'appel de la fonction les questions, vous pourriez envisager de le mettre dans la tête, mais dans ce cas, (a) vous souhaiterez probablement de les déclarer en tant que bien, et (b) vous avez déjà fait toutes les autres optimisations que vous pouvez trouver.
En bref, sauf si vous savez au-delà de l'ombre d'un doute que vous avez besoin de votre fonction statique dans un fichier d'en-tête... vous ne voulez pas d'une fonction statique dans un fichier d'en-tête; vous voulez un non-statique de la fonction dans un .c fichier d'en-tête dans le .h.
Dans mon expérience, il est généralement une mauvaise idée de définir une fonction dans un .h fichier, et je n'ai jamais eu l'occasion de le faire, le faire par accident une fois m'a causé de maux de tête.
Si je suppose que cela permettrait à chaque fichier qui contient l'en-tête de disposer de son propre séparé mise en œuvre de la fonction qui, si la fonction est statique vars, peut-être que le comportement souhaité par ex. si vous voulez/besoin de garder une trace de certaines informations séparément pour chaque fichier.
Moderne C a adopté la
inline
mot clé de C++ pour une telle tâche. Mais si votre compilateur n'a pas (encore?)static
dans les fichiers d'en-tête est une façon d'imiter cela.inline
ne veut pas dire que la fonction est nécessairement intégrées à tous les appelants, mais juste qu'il y aura généralement au plus une copie de l'exécutable final. (Techniquement, le correspondant de l'éditeur de liens symboles sont "faibles" symboles.) En revanche, si juste déclaréstatic
chaque unité de compilation va en garder une copie.Une telle approche d'avoir des définitions de fonction dans les en-têtes doivent être limités à petit fonctions qui font de petites tâches pour lesquelles votre compilateur peut améliorer le code de façon substantielle si elle est optimisée dans la fonction appelante.
Quand vous le faites, soyez également prudent avec la mise en œuvre de ces fonctions. Vous risquez de casser votre possibilité d'inclure les déclarations en C++ par qui. Généralement les deux langues qu'être d'accord (pour la plupart) sur les interfaces, pas nécessairement pour la mise en œuvre, il y a de subtiles différences.
Peut également être utile de définir des fonctions avec le travail statique, tampons local pour chaque unité de traduction. Un exemple particulier est strtok(). strtok() marche à travers un tampon d'un jeton par appel. Si strtok() les appels sont entrelacés de deux endroits différents (c'est à dire deux unités de traduction), alors les résultats ne sont pas ce qui est attendu ou souhaitée. Si chaque unité de traduction avait sa propre copie de strtok() et, par conséquent, chaque unité de traduction avait sa propre strtok (), les variables statiques, alors ce genre de buter sur l'état interne allait s'en aller. Si l'état de piétinement qui se passe, puis deux (ensembles de) les appels sont dans la même unité de traduction et la mise au point a l'apparence de la localité.
(À noter que la "bonne" solution est de remplacer strtok() avec un apatride, de la fonction et de faire des appels est responsable de la tenue contexte et de l'état de l'information, de la même façon fopen() et ses amis font l'appelant tenir un dossier pour chaque contexte.)
Si la fonction a une liaison externe, il doit être déclarée dans un .h fichier.
Si la fonction est statique et n'a donc aucune liaison externe, la fonction ne doit être déclarée dans la .c fichier dans lequel elle est définie.
Il n'est jamais bon pour avoir une fonction définie dans un fichier d'en-tête.