GCC inline-funcția de lucru la fel de rapid ca un macro, avr, programare

Cu ajutorul funcției încorporate (inline), puteți instrui CCG pentru a face apeluri de funcții mai rapid. Unul dintre modurile în care CCG poate realiza acest lucru - pentru a introduce codul în funcția a corpului este locul în care funcția este numit. Acesta este procesat procesor mai rapid, deoarece elimină costul unui apel de funcție și să se întoarcă de la ea. Mai mult decât atât, în cazul în care oricare dintre argumentele reale ale funcției este o constantă, valorile lor cunoscute pot fi luate în considerare la momentul compilării, prin care pot fi construite nu toate funcțiile corpului. Rezultatul va fi că dimensiunea de cod este mai puțin previzibil; cod obiect poate crește sau descrește cu utilizarea funcțiilor încorporate, în funcție de fiecare caz în parte. Puteți specifica, de asemenea, să CCG încerca să integreze toate „suficient de simple“ funcții în locul unui apel, dacă utilizați opțiunea -finline-funcții. Aici sunt traduceri ale articolelor [1, 2].

CCG implementează 3 semantici diferite pentru declararea inline funcții. Una dintre ele este disponibil cu opțiunea -std = gnu89 sau -fgnu89-inline, sau atunci când există un atribut pentru toate inline-declarații, celălalt utilizând opțiunile -std = C99, -std = c11, -std = gnu99 sau -std = gnu11 ( fara -fgnu89-inline), și un al treilea, folosind un mod de compilare C ++.

Pentru a declara funcția încorporată, utilizați în declarația sa inline de cuvinte cheie, astfel:

Dacă scrieți un fișier antet, plug-in programele ISO C90, în loc de cuvinte cheie utilizează __inline__ inline (pentru detalii vezi. Caseta „Înlocuirea cuvinte cheie“).

Metoda razrulit aceste probleme - a pus „__“ la începutul și sfârșitul fiecărui cuvânt cheie problematice. De exemplu, în loc de a folosi __asm__ asm și __inline__ în loc de inline.

Alte compilatoare C nu acceptă aceste cuvinte cheie alternative; Dacă doriți să compilați codul de la un alt compilator, puteți specifica definiții pentru cuvinte cheie alternative ca macro-uri pentru a le înlocui cu cuvinte cheie personalizate. Se pare ceva de genul:

Opțiunea -pedantic și alții să conducă la avertismente pentru mai multe extensii GNU C. Puteți dezactiva aceste avertismente într-o singură expresie scriind __extension__ înainte de exprimare. Expresia __extension__ va avea nici un efect în cazul în care este utilizat în contextul greșit.

Aceste trei tipuri de integrare să se comporte în acest fel, în două cazuri importante: atunci când cuvântul cheie inline este utilizat într-o funcție (statică), similar cu exemplul de mai sus, iar când funcția a fost prima este declarată fără inline de cuvinte cheie, static și apoi a fost definit ca fiind în linie, ca aceasta :

În ambele aceste cazuri, programul se comportă la fel ca și în cazul în care nu ați utilizat direct, cuvântul cu excepția faptului că se schimbă viteza de execuție.

Vă rugăm să rețineți că unele utiliza anumite caracteristici fac imposibilă inline-substituție. De exemplu: variadic-funcție (o funcție cu un număr variabil de argumente), utilizarea alloca, utilizat Goto calculat (. Vezi caseta „etichete ca valori“), Utilizarea Goto non-locale, folosind imbricate funcții (imbricate) utilizează setjmp, utilizați __builtin_longjmp și utilizați __builtin_return sau __builtin_apply_args. Opțiunea -Winline vă va alerta la situațiile în care funcția este marcat ca inline, dar nu poate fi realizată încorporarea, și oferă, de asemenea motivul pentru acest lucru.

Pentru a utiliza această valoare, aveți nevoie pentru a face tranziția pentru el. Acest lucru se face pe operatorul calculat de tranziție (Goto calculat), Goto * exp; (1). De exemplu:

Permise orice expresie de tip void *.

O modalitate de a utiliza aceste constante - inițializarea unui tablou static, care este tratat ca un tabel de salt:

După aceea puteți alege o etichetă pe index, ca aceasta:

Rețineți că acest lucru nu se va face prin verificarea pentru a merge dincolo de indicele de matrice C nu se face automat.

O astfel de matrice de valori de etichete este utilizat pentru aceleași scopuri ca și comutatorul de operator. Cu toate acestea, comutatorul mai clar pentru a citi, astfel încât întotdeauna l utilizați în loc de o serie de etichete, cu excepția cazurilor când comutatorul nu este potrivit pentru aplicația dumneavoastră.

O altă utilizare a valorilor etichetei - interpret pentru codul în linie. Tag-uri în cadrul funcțiilor de coajă pot fi stocate în codul de flux pentru ramificarea ultrarapida.

Un mod alternativ de a scrie exemplul precedent:

Acest cod este mai ușor de utilizat pentru a fi utilizate în bibliotecile partajate, deoarece reduce numărul de mișcări necesare și, prin urmare, permite utilizarea datelor read-only. Această alternativă la diferențele de etichete nu sunt acceptate pentru procesor AVR, utilizați prima opțiune pentru ei.

În conformitate cu cerințele standardului ISO C ++, a declarat funcțiilor CCG - membrii clasei (de exemplu, funcțiile definite în corpul clasa ..) este marcat ca linie, chiar dacă acestea nu sunt declarate în mod explicit cu inline de cuvinte cheie. Puteți trece peste acest comportament folosind opțiunea -fno-default-inline (pentru detalii, a se vedea. Descrierea opțiunilor care controlează dialectul C ++ [3]).

CCG nu Lipeste orice funcții, atunci când nu se face de optimizare, cu excepția cazului dacă specificați atributul always_inline pentru o funcție de genul:

Restul acestei secțiuni se referă la încorporarea GNU C90.

Când inline-funcția nu este o statică (atribute non-statice), atunci compilatorul ar trebui să se înțeleagă că nu pot prelua apeluri loc de alte fișiere sursă; ca simbol la nivel mondial poate fi definit numai într-un singur loc în program, această funcție nu ar trebui să fie definite în alte fișiere sursă, astfel încât apelurile de funcții nu poate fi construit. Astfel, funcțiile de bază non-statice sunt întotdeauna compilate în codul selectat, ca de obicei.

Această combinație de linie și dă efectul extern macro. Utilizați metoda - pune definiția funcției cu aceste cuvinte cheie în fișierul antet, și puneți o altă copie a definiției (fără inline și extern) într-un fișier bibliotecă. Definiție în fișierul antet va provoca cele mai multe apeluri la funcția va fi construit. Dacă există orice utilizare a funcțiilor care va apela la ea ca un singur exemplar în bibliotecă.

[Built-in funcție în limbajul C, în contextul portabilitatea codului]

La punctul de aplicare a funcției de compilator încorporat este un indiciu că trebuie să ia unele măsuri în scopul de a apela funcția mai repede decât s-ar fi făcut în mod normal. Cel mai adesea, aceste acțiuni constau în faptul că, în locul apelului va înlocui corpul funcției, fără a apela operatorul. Pentru că atunci când această înlocuire nu este necesar de instrucțiuni pentru a apela (apel) și a reveni (ret), și nu este necesar să se păstreze stiva variabilele locale și sunt folosite registre, acest lucru dă compilatorul pentru a efectua anumite optimizări atunci când combină funcțiile de cod și programul principal.

Există mai multe modalități de a determina inline-funcții; orice definiție vedere existentă ar genera cu siguranță un cod obiect de sine stătător, sau cu siguranță nu generează un cod obiect de sine stătător, sau de a genera un cod obiect autonom numai dacă știți că aveți nevoie de ea. Uneori, acest lucru poate duce la duplicarea codului obiect, ceea ce reprezintă o problemă potențială pentru următoarele motive:

• este pierdut memoria.
• poate duce la faptul că indicii la aceeași funcție nu sunt egale între ele.
• poate reduce eficacitatea cache de instrucțiuni (deși inserția ar putea fi, de asemenea, face în alte moduri).

Dacă oricare dintre următoarele este o problemă pentru tine, puteți utiliza strategia pentru a ocoli duplicarea codului. Tocmai este discutat în articol.

Sub unitate de afaceri pentru a înțelege codul sursă separată de modul (fișier) în C. funcții statice și variabile statice sunt reguli speciale de aplicare se aplică pentru a difuza unități.

[reguli inline pentru C99 standard]

1. Funcția în care toate declarația sa (inclusiv definiții) sunt etichetate în linie și nu ca extern. Acesta trebuie să fie definit într-o singură unitate de traducere (unitate de traducere). Standardul se referă la această opțiune ca o definiție inline (definiția inline). Nu va fi nici un cod obiect separat generat, astfel încât această definiție nu poate fi apelat de la o altă unitate de difuzare (de la un alt modul).

Puteți (2) au o definiție separată (nu în linie) din aceeași funcție într-o altă unitate de traducere, compilatorul poate alege o definiție separată sau inline-definition.

Aceste funcții nu pot conține variabilele statice modificabili, și nu pot avea acces la definițiile sau funcțiile statice într-un alt fișier sursă (t. E., în cazul în care nu inline-funcțiile sunt declarate).

În acest exemplu, toate declarațiile și definițiile utilizate în linie, dar nu folosiți extern:

Această funcție nu poate fi numit de la alte fișiere; În schimb, într-un alt fișier trebuie să aibă o definiție proprie.

Nota (2): în standardul nu există nici o descriere clară a acesteia. El spune că inline-determinare nu interzice în afara (extern) definiția în altă parte, dar apoi oferă o alternativă la definiții externe. Din păcate, acest lucru nu oferă o înțelegere clară - ar trebui să existe în afara este de fapt definiția. În practică, dacă nu stabilite pentru a tortura compilator, atunci nu va fi următoarea regulă: dacă doriți să salvați funcția încorporată este complet privat pentru o unitate de traducere, fă-o definit ca inline statice.

2. Funcția, în cazul în care cel puțin o declarație de marcat ca fiind în linie, dar în cazul în care alte declarații nu menționează în linie, sau denumite extern. Determinarea funcției trebuie să fie în aceeași difuzare yunite această declarație. cod obiect separat va fi generat (cum ar fi, pentru funcția normală) și poate fi apelat de la alte unități de difuzare program.

Este, de asemenea, utilizat pentru a limita definiția statică, deja menționată mai sus.

În acest exemplu, toate declarațiile și definițiile utilizate în linie, dar adaugă extern:

În acest exemplu, una dintre declarațiile nu este marcat ca fiind inline:

În oricare dintre aceste două exemple, funcția poate fi apelat de la alte fișiere.

3. Funcția este definită ca o linie statică. definiție locală pot fi emise, dacă este necesar. Puteți avea mai multe definiții în program, difuzate în unități diferite, iar acestea vor funcționa toate funcțiile ca separate. Pur și simplu aruncarea înapoi în linie reduce portabilitatea programelor (din nou, ceteris paribus).

Acest lucru poate fi util pentru mici, care altfel ar putea fi definite ca macro-uri. Dacă funcția nu este întotdeauna construit în, atunci veți obține un duplicat de cod cu toate problemele deja descrise mai sus.

O abordare rațională ar fi de a plasa o funcție inline statică într-un fișier antet, sau în cazul în care ar trebui să fie utilizat pe scară largă, sau pur și simplu în fișierele de cod sursă care utilizează aceste caracteristici - în cazul în care au folosit vreodată în acest fișier.

În acest exemplu, funcția este definită ca o linie statică:

Primele două opțiuni sunt în mod natural combinate. Ești fie toate în linie și într-un singur loc extern pentru o definiție autonomă a interogare, sau scrie inline aproape peste tot, dar omiteți necesară o dată pentru a obține o definiție autonomă.

Funcția principală nu poate fi încorporat (inline) funcția.

(C ++ reguli mai stricte:. O caracteristică care a apărut undeva ca linie, toți ar trebui să fie definite ca inline, și ar trebui să fie definite în același mod în toate unitățile de traducere, în cazul în care acesta este utilizat)

[Inline reguli pentru GNU C Compiler]

1. Funcția definită în linie pe cont propriu. Întotdeauna auto-generat codul obiect. Puteți scrie o singură definiție ca acest lucru pentru întregul program. Dacă doriți să-l utilizați de la alte unități de traducere, plasați declarația în fișierul antet; dar nu va face integrarea în modulele de difuzare, în care se utilizează antetul.

Această opțiune este de utilizare limitată, dacă doriți să utilizați o funcție într-o traducere yunite, face mai mult sens pentru a face inline static, așa cum se arată în opțiunea 3 - dacă, eventual, nu ar vrea să aibă o formă care să permită funcții să fie construite în mai mult de o unitate difuzare.

Cu toate acestea, această opțiune este utilizarea de cuvinte cheie în linie are avantajul de a programului este redus la un program portabil cu aceeași valoare (dacă nu folosiți nici un alt design de non-portabil).

2. Funcția, definită ca inline extern. Stand-alone cod obiect nu este generat niciodată. Puteți avea mai multe dintre aceste definiții, iar programul va funcționa în continuare. Cu toate acestea, de asemenea, trebuie să adăugați definiția undeva și nu-inline, în cazul în care nu funcționează undeva utilizat ca inline.

Aceasta oferă o semantică rezonabile (este posibil să se evite suprapunerea funcțiilor de cod obiect), dar un pic incomod de folosit.

O modalitate de a folosi această opțiune - pune definițiile în fișierul antet, surround, operatorul Preprocessor #if, care vor fi evaluate la adevărat sau atunci când se utilizează GNU C, sau când antetul este conectat dintr-un fișier care conține definiția emis (indiferent dacă sunt sau nu GNU C ). În cazul în care acesta din urmă a omis extern (de exemplu, scrie EXTERN, și este determinată prin #define fie ca extern, fie ca un gol). ramură #else ar conține o declarație de funcții pentru compilatoare non-GNU.

3. Funcția, definită ca inline statice. Dacă este necesar, un cod obiect de sine stătător va fi generat. Puteți avea mai multe definiții în program, difuzate în unități diferite, și va funcționa. Aceasta este aceeași versiune de realizare că, pentru regulile C99.

Cu eliberare 4.3 compilatorul C GNU acceptă regulile de încorporare C99, așa cum este descris mai sus, și le utilizează în mod implicit, cu opțiuni de -std = C99 sau -std = gnu99. Regulile vechi pot fi solicitate în noua opțiune compilator -gnu89-inline, sau folosind atributul funcției gnu_inline.

În cazul în care C99 sunt reguli care determină macro CCG __GNUC_STDC_INLINE__. Începând cu GCC 4.1.3 este __GNUC_GNU_INLINE__ macro, dacă este folosit doar normele CCG, dar vechile compilatoare utilizează aceleași reguli fără a urma nici un macro. Puteți corecta situația, folosind o bucată de cod, cum ar fi următoarele:

[Strategii pentru utilizarea inline funcții]

Următoarele reguli sunt sfătuiți să posibile modele de utilizare inline-funcții, care afectează mai mult sau mai puțin portabilitate.

De exemplu, în fișierul antet:

Puteți sprijini compilatoare moștenite (de exemplu, non-inline) prin -Dinline = opțiunea „“ deși aceasta va duce la pierderi de memorie, în cazul în care compilatorul nu optimizează funcțiile neutilizate.

GNU C. Modelul Utilizare inline extern în fișierul antet generală și să dea definiția undeva în fișierul .c, eventual folosind un macro - pentru a asigura apariția peste tot din același cod. De exemplu, în fișierul antet:

și specificați doar o singură sursă de fișier de cod:

Modelul C99. Utilizați linie în fișierul antet generală, și să ofere o definiție undeva în fișierul .c, prin declarația externă. De exemplu, într-un fișier antet:

și numai unul din o parte din fișier cu cod sursă:

Pentru a adăuga suport pentru compilatoare mai mari, va trebui să plătească toate acest cod pentru un preprocesor, astfel încât declarația ar putea fi văzut în antetul comun, și determinarea au fost limitate la o unitate de afaceri de traducere, în care funcția este definită prin linie.

Complex model de portare. Utilizați un macro pentru a selecta definiția sau folosind inline pentru GNU C extern, în linie la C99, sau fără nici un fel de ea. De exemplu, în antet:

și numai fișier de cod o singură sursă:

Susținem compilatoare moștenite au aceleași probleme ca și cu GNU C. model de

1. Funcții inline În site-ul C: greenend.org.uk.
2. Un Inline Funcția este la fel de rapid ca un site Macro: gcc.gnu.org.
3. Controlul site-ului Opțiuni C ++ Dialect: gcc.gnu.org.