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.
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 ).
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 .
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 .
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.
C programozási nyelv | |
---|---|
Fordítók |
|
Könyvtárak | |
Sajátosságok | |
Néhány leszármazott | |
C és más nyelvek |
|
Kategória:C programozási nyelv |