Fejléc fájl

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt hozzászólók, és jelentősen eltérhet a 2016. február 28-án felülvizsgált verziótól ; az ellenőrzések 20 szerkesztést igényelnek .

A programozásban a fejlécfájl ( angolul  header file ) vagy a beépített fájl olyan fájl, amelynek tartalmát az előfeldolgozó  automatikusan hozzáadja a forrásszöveghez azon a helyen, ahol valamilyen direktíva{$I file.inc} található ( Pascalban , #include <file.h>C-ben).

A C és C++ programozási nyelvekben a fejlécfájlok az elsődleges módja annak , hogy egy másik modulban használt adattípusokat , struktúrákat, függvényprototípusokat , felsorolt ​​típusokat és makrókat helyezzenek el egy programba. Az alapértelmezett kiterjesztés a .h ; néha a .hpp kiterjesztést használják a C++ fejlécfájlokhoz .

Ugyanannak a kódnak az újbóli felvételének elkerülése érdekében direktívákat használnak #ifndef, #define, #endif.

A fejlécfájl általában bármilyen programnyelvi konstrukciót tartalmazhat , de a gyakorlatban a végrehajtható kód (a C++ nyelven belüli függvényei kivételével ) nem kerül fejlécfájlokba. Például az egynél több fájlban deklarálandó azonosítók kényelmesen leírhatók egy fejlécfájlban, majd szükség szerint hozzáadhatók. A modularitás a legtöbb összeszerelőben ugyanúgy működik .

Hagyományosan a fejlécfájlok C és C++ szabványos könyvtári függvényeket deklarálnak .

Más nyelveken (például Pascalban ) fejlett modulrendszert használnak. De még bennük is van egy bizonyos érték a fejlécfájloknak. A helyzet az, hogy két fájl (fő és fejléc) egy fordítási egységbe egyesül , ezért a fejlécfájl tartalmazhat előfeldolgozó direktívákat , befejezetlen szintaktikai konstrukciókat.

Időpont

A modern programozási nyelvekben a programok külön-külön összeállított modulokból állnak. Ezzel kapcsolatban felmerül a kérdés: hogyan jelezzük, hogy egy szubrutin vagy egy változó X definiálva van egy modulban Y? Erre több megoldás is létezik, C -ben ezt alkalmazzák.

Az egyik fordítási egységben (azaz с-fájlban) egy függvény le van írva, például:

int add ( int a , int b ) { return a + b ; }

Ahhoz, hogy más fordítási egységekből hivatkozni lehessen rá, deklarálni kell egy függvény prototípus segítségével , azaz:

int add ( int , int ); int tripla ( int x ) { return add ( x , add ( x , x )); }

Azonban egy ilyen deklaráció megköveteli a programozótól, hogy addkét helyen adja meg a funkció deklarációját - a megvalósítást tartalmazó fájlban és abban a fájlban, amelyben azt használják. Ha egy függvénydefiníció megváltozik, a programozónak ne felejtse el frissíteni a programban használt összes prototípust.

A fejlécfájl az egyik megoldás erre a problémára. A modul fejlécfájlja deklarál minden olyan függvényt , objektumot és adattípust , amely a modul meghívási felületének részét képezi – például ebben az esetben a fejlécfájl csak függvénydeklarációt tartalmazhat add. Minden függvényre hivatkozó forrásfájlnak adddirektívát kell használnia #includea fejlécfájlba:

/* triple.c fájl */ #include "add.h" int tripla ( int x ) { return add ( x , add ( x , x )); }

A fejlécfájlban lévő inicializált konstansok listáit az előfeldolgozó választja ki , hogy lecserélje a benne lévő fájlban lévő állandók értékére. A beépített fejlécfájl-függvényeket az előfeldolgozó makrovédelmi direktívái keretezik, hogy elkerüljék azok megkettőzését az include fájlban (ilyen helyzet fordulhat elő osztály- vagy fájlöröklődés esetén ):

/* Add.h fájl */ #ifndef ADD_H #define ADD_H int add ( int , int ); #endif /* ADD_H */

A tervezésen kívül #ifndef - #endifnéha nem szabványosat is használnak #pragma once:

/* Add.h fájl */ #pragma egyszer int add ( int , int );

A fejlécfájlok egyszerűbbé teszik a karbantartást – ha egy definíció megváltozik, csak egy deklarációt (a fejlécfájlban lévőt) kell frissíteni . A forrásfájlokban használt definíciókat tartalmazó fejlécfájlt is beilleszthet a forrásfájlba. Ez lehetővé teszi a fordító számára, hogy ellenőrizze, hogy a h-file deklarációja megegyezik-e a -file definíciójával c:

/* Add.c fájl */ #include "add.h" int add ( int a , int b ) { return a + b ; }

A fejlécfájlok általában csak az interfész pontosabb meghatározására szolgálnak, és általában megjegyzéseket tartalmaznak, amelyek elmagyarázzák, hogyan használhatók a fájlban deklarált összetevők . A fenti példában a használt szubrutinok külön forrásfájlokra vannak szétválasztva, amelyeket külön kell lefordítani (a C és C++ nyelvben kivételt képeznek az inline függvények , amelyek gyakran szerepelnek a fejlécfájlban, mivel a legtöbb használatban Ilyen esetekben nem lehetséges az inline függvény helyes bővítése anélkül, hogy a fordítási időben meg kellene hívni a definíciójukat ).

Összehasonlítás a fejlécek közvetlen lekérésével egy lefordított modulból

A fejlécfájlok alternatívája, hogy közvetlenül a lefordított modulból kapunk információkat a deklarált típusokról, függvényekről stb. A Pascal , a Java és mások ezt teszik .

Előnyök

A fejlécfájlok előnye elsősorban a fordító egyszerűsítése: fejlécfájlok nélkül a fordító és a linker ugyanazt a feladatot végzi el, amikor ellenőrzi, hogy egy modul tartalmaz-e Ylefordított függvényt X.

Ha egy modul helyesen van megírva, a feltételes fordítás letilthatja egyes funkcióit. Például ebben az esetben megtagadjuk egy hatalmas STL -könyvtár csatolását a programhoz :

// unit.h #ifndef __UNIT_H__ #define __UNIT_H__ #ifndef UNIT_STL_UNUSED #include <iostream> void dump ( std :: ostream & os ); void dump () { dump ( std :: cout ); } #endif üresjárat ( ); #endif // main.cpp #define UNIT_STL_UNUSED #include "unit.h" int main () { futni (); return 0 ; }

Ha a modul már lefordítva van terjesztve (könyvtár), akkor a fejléc fájl egyben a modul használatának dokumentációja is lesz.

Ha a programozó kijavítja egy függvény megvalósítását egy c-fájlban anélkül, hogy megérintené a fejlécet, ez nem idézi elő az összes, a fejlécet használó modul kaszkádos újrafordítását.

A fejlécfájl lehetővé teszi olyan dolgok megadását, amelyeket nem lehet modulokkal megadni - helyettesítéseket -val #define, fordítói direktívákat , befejezetlen szintaktikai konstrukciókat...

Leegyszerűsíti a különböző nyelveken írt modulok közötti interakciót. A fordítónak és a linkernek egyáltalán nem mindegy, hogy a hívott modul ugyanazon a nyelven vagy más nyelven íródott. Ezenkívül a különböző nyelvek moduljaikat ugyanabba az objektumfájlba fordíthatják - ebben az esetben több nyelvhez kap egy linkert. Hasonlóképpen könnyű olyan könyvtárat készíteni, amelyet a felhasználó úgy dönt, hogy CPP-fájlként beilleszt egy projektbe, előre lefordítva, statikusan csatolva, vagy DLL -ként csatolva .

Hátrányok

A fejlécfájlok sokkal lassabbak – 10 fájl lefordításához c, mindegyikhez egy hosszú fájl van csatolva , a hfordítónak 10-szer át kell mennie a fejlécen. Ennek a problémának a megoldására sok fordító az előrefordított .

A fejlécfájlok a C++ nyelv egyes objektumaival ( konstansok , inline-függvények, sablonok , static-változók) együtt nehéz konstrukciókat alkotnak.

A programozónak két helyen szinkronban kell változtatnia a függvényfejléceket. Ha megváltoztatta ca -file-t, és elfelejtette megtenni ugyanezt a h-file-lel, akkor a linker homályos hibaüzenetet ad sorszám nélkül. Ez különösen észrevehető a C++ -ban, ahol ugyanannak a függvénynek különböző argumentumkészlete lehet , és a fordítói szintű ellenőrzés nem működik. Ha egy programozó véletlenül befejezetlenül hagyott egy konstrukciót egy h-file-ben, akkor a hiba egy teljesen más c-vagy h-fájlban lesz.

A C család nyelveiből származó projekteket összetett projekt-összeállítási sémák jellemzik. Végül is (legalábbis a szabványos C ++-ban) be kell építeni egy könyvtárat a projektbe - akár CPP-fájlok formájában, akár lefordított formában. Még ha (például a Visual C++-ban) előfeldolgozó direktívák is vannak erre, a könyvtárat akkor is fel kell építeni.

Lásd még

Linkek

Irodalom

  • Podbelsky V.V. 8. fejezet Előfeldolgozó eszközök // C++ nyelv / rec. Dadaev Yu. G. - 4. - M . : Pénzügy és statisztika , 2003. - P. 263-280. — 560 p. - ISBN 5-279-02204-7 , UDC 004.438Si (075.8) LBC 32.973.26-018 1ya173.