[so] [Indicatii generale teme]Definitii de functii non-statice in headere
Vlad Dogaru
ddvlad at herebedragons.ro
Mon Feb 25 18:19:49 EET 2013
On Mon, Feb 25, 2013 at 03:37:25PM +0000, Mihail-Daniel STĂNCIULESCU wrote:
> Salut,
>
> In lista de depunctari pentru teme exista un punct unde scrie ca
> definitiile de functii non statice in headere sunt depunctate.
> * Imi puteti explica va rog ce inseamna acest lucru deoarece nu gasesc
> nici un exemplu in acest sens in alte articole de coding style?
> * Unde putem defini functiile non-statice astfel incat sa nu duplicam
> codul lor in fiecare fisier in care sunt folosite?
> * In headerele de C din sistem am gasit ca functiile sunt definite cu
> extern. La acest lucru se refera punctul din lista de depunctari?
(1)
Dacă definești asta într-un header:
/* În foo.h */
int foo(int x)
{
return 0;
}
și acel header este inclus de două fișiere sursă, ambele fișiere obiect
(.o) rezultate din compilare vor conține cod pentru funcția foo.
Dacă cele două obiecte sunt link-editate împreună, linker-ul dă cu
eroare, pentru că există două simboluri cu același nume:
/tmp/ccAWkbPI.o: In function `foo':
bar.c:(.text+0x0): multiple definition of `foo'
/tmp/ccpwlOcl.o:foo.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
***
(2)
Ce _vrei_, de fapt, să faci, e să declari funcția ca extern în header
(în cazul ăsta, extern e opțional):
/* În foo.h */
extern int foo(int x);
În unul dintre fișierele sursă C implementezi funcția:
/* În foo.c */
int foo(int x)
{
return 0;
}
Și în celălalt fișier incluzi header-ul, care spune că există funcția,
dar nu dă și implementarea ei:
/* În bar.c */
#include "foo.h"
/* ... */
printf("%d\n", foo(0));
La compilare, simbolul foo va fi unresolved în bar.o, dar asta e ok,
pentru că va fi rezolvat de linker în etapa de link-editare -- va fi
folosit simbolul din foo.o.
***
(3)
O variantă mai puțin tipică (dar foarte utilă) e folosită, printre
altele, de kernel-ul Linux:
Dacă vrei să ai o funcție inline (din rațiuni de performanță), ea
trebuie să fie prezentă în sursa curentă, pentru că nu linker-ul, ci
compilatorul, face inlining. Or, în varianta prezentată mai sus,
compilatorul nu are sursa lui foo în bar.c și nu poate face inlining.
Soluția este să îl declarăm pe foo în header, _dar_ acesta trebuie să
fie static:
/* În foo.h */
static inline int foo(int x)
{
return 0;
}
Cuvântul cheie static înseamnă că simbolul foo nu va fi exportat de
modul, deci linker-ul nu se va plânge că există două foo-uri.
Două referințe utile:
[1] http://stackoverflow.com/questions/4576607/static-keyword-in-ansi-c
[2] http://kernel.org/doc/local/inline.html
***
Concluzie:
Tu vrei, de obicei, varianta (2). Varianta (1) este incorectă, iar (3)
este o optimizare.
Guideline-ul este formulat astfel încât sunt permise (2) și (3), dar nu
și (1). De-asta pomenește de funcții non-statice în headere.
Hope this helps,
Vlad
More information about the so
mailing list