Ohjelmoinnissa otsikkotiedosto ( englanniksi header file ) tai sisällytetty tiedosto on tiedosto, jonka sisällön esiprosessori lisää automaattisesti lähdetekstiin paikassa, jossa jokin direktiivi sijaitsee ( {$I file.inc}Pascalissa , C: ssä#include <file.h> ).
C- ja C++ - ohjelmointikielissä otsikkotiedostot ovat ensisijainen tapa sisällyttää ohjelmaan tietotyyppejä , rakenteita, funktioprototyyppejä , lueteltuja tyyppejä ja makroja , joita käytetään toisessa moduulissa. Oletustunniste on .h ; _ joskus .hpp -tunnistetta käytetään C++- otsikkotiedostoissa .
Saman koodin uudelleen sisällyttämisen välttämiseksi käytetään direktiivejä #ifndef, #define, #endif.
Otsikkotiedosto voi yleensä sisältää mitä tahansa ohjelmointikielen rakenteita , mutta käytännössä suoritettavaa koodia (lukuun ottamatta sisäisiä toimintoja C++ : ssa ) ei sijoiteta otsikkotiedostoihin. Esimerkiksi tunnisteet , jotka on ilmoitettava useammassa kuin yhdessä tiedostossa, voidaan kuvata kätevästi otsikkotiedostossa ja sisällyttää tarvittaessa. Modulaarisuus toimii samalla tavalla useimmissa kokoonpanijoissa .
Perinteisesti otsikkotiedostot ilmoittavat C- ja C++- standardikirjastofunktiot .
Muilla kielillä (esimerkiksi Pascalissa ) käytetään kehitettyä moduulijärjestelmää. Mutta jopa niissä otsikkotiedostoilla on tietty arvo. Tosiasia on, että kaksi tiedostoa (pää- ja otsikko) yhdistetään yhdeksi käännösyksiköksi , ja siksi otsikkotiedosto voi sisältää esikäsittelyohjeita , keskeneräisiä syntaktisia rakenteita.
Nykyaikaisissa ohjelmointikielissä ohjelmat koostuvat moduuleista , jotka on käännetty erikseen. Tässä yhteydessä herää kysymys: kuinka ilmaistaan, että aliohjelma tai muuttuja X on määritelty moduulissa Y? Tähän on olemassa useita ratkaisuja, C :ssä sitä sovelletaan.
Yhdessä käännösyksikössä (eli с-tiedostossa) kuvataan funktio, esimerkiksi:
int add ( int a , int b ) { palauttaa a + b ; }Jotta siihen voidaan viitata muista käännösyksiköistä, se on ilmoitettava käyttämällä funktion prototyyppiä , eli:
int add ( int , int ); int kolmois ( int x ) { return add ( x , add ( x , x )); }Tällainen ilmoitus edellyttää kuitenkin, että ohjelmoija toimittaa toiminnon ilmoituksen addkahdessa paikassa - sen toteutuksen sisältävässä tiedostossa ja tiedostossa, jossa sitä käytetään. Jos funktion määritelmä muuttuu, ohjelmoijan tulee muistaa päivittää kaikki ohjelmassa käytetyt prototyypit.
Otsikkotiedosto on yksi ratkaisu tähän ongelmaan. Moduulin otsikkotiedosto ilmoittaa jokaisen funktion , objektin ja tietotyypin , joka on osa moduulin kutsuliitäntää – esimerkiksi tässä tapauksessa otsikkotiedosto voi sisältää vain funktion ilmoituksen add. Jokaisen funktioon viittaavan lähdetiedoston addon käytettävä ohjetta #includeotsikkotiedoston sisällyttämiseksi:
/* Tiedosto triple.c */ #include "add.h" int kolmois ( int x ) { return add ( x , add ( x , x )); }Esiprosessori valitsee otsikkotiedoston alustettujen vakioiden luettelot korvattavaksi näiden vakioiden arvoilla sisällytetyssä tiedostossa. Sisällytetyt otsikkotiedostofunktiot kehystetään esiprosessorin makrosuojausohjeilla , jotta vältetään niiden päällekkäisyys sisällyttävässä tiedostossa (sellainen tilanne voi tapahtua luokan tai tiedoston periytymisen yhteydessä ):
/* Tiedosto add.h */ #ifndef ADD_H #define ADD_H int add ( int , int ); #endif /* ADD_H */Suunnittelun lisäksi #ifndef - #endifkäytetään joskus epästandardia #pragma once:
/* Tiedosto add.h */ #pragma kerran int add ( int , int );Otsikkotiedostot helpottavat ylläpitoa - kun määritelmä muuttuu, vain yksi ilmoitus (otsikkotiedostossa oleva) on päivitettävä . Voit myös sisällyttää lähdetiedostoon otsikkotiedoston, joka sisältää lähdetiedostoissa käytetyt määritelmät. Tämän avulla kääntäjä voi tarkistaa, vastaako -tiedoston ilmoitus h-tiedoston määritelmää c:
/* Tiedosto add.c */ #include "add.h" int add ( int a , int b ) { palauttaa a + b ; }Tyypillisesti otsikkotiedostoja käytetään vain rajapinnan selkeämpään määrittelyyn, ja ne sisältävät yleensä kommentteja, joissa selitetään, kuinka tiedostossa ilmoitettuja komponentteja voidaan käyttää. Yllä olevassa esimerkissä käytetyt aliohjelmat on erotettu erillisiksi lähdetiedostoiksi, jotka on käännettävä erikseen (poikkeuksena C- ja C++-kielissä ovat inline-funktiot , jotka sisältyvät usein otsikkotiedostoon, koska useimmissa käyttötavoissa tapauksissa ei ole mahdollista laajentaa rivifunktiota oikein ilman kutsua niiden määritelmään käännösaikana ).
Vaihtoehto otsikkotiedostoille on saada tietoja ilmoitetuista tyypeistä, funktioista jne. suoraan käännetystä moduulista. Pascal , Java ja muut tekevät tämän .
Otsikkotiedostojen etu on ensisijaisesti kääntäjän yksinkertaistaminen: ilman otsikkotiedostoja kääntäjä ja linkittäjä tekevät saman työn tarkistaakseen, sisältääkö moduuli Ykäännetyn toiminnon X.
Jos moduuli on kirjoitettu oikein, ehdollinen käännös voi poistaa osan sen toiminnoista. Esimerkiksi tässä tapauksessa emme halua linkittää valtavaa STL -kirjastoa ohjelmaan :
// unit.h #ifndef __UNIT_H__ #define __UNIT_H__ #ifndef UNIT_STL_UNUSED #include <iostream> void dump ( std :: ostream & os ); void dump () { dump ( std :: cout ); } #loppu Jos tyhjä juoksu (); #loppu Jos // main.cpp #define UNIT_STL_UNUSED #include "unit.h" int main () { juosta (); paluu 0 ; }Jos moduuli on jaettu jo käännettynä (kirjasto), otsikkotiedosto on samalla dokumentaatio moduulin käytöstä.
Jos ohjelmoija korjaa funktion toteutuksen c-tiedostossa koskematta otsikkoon, tämä ei aiheuta peräkkäistä uudelleenkääntämistä kaikista kyseistä otsikkoa käyttävistä moduuleista.
Otsikkotiedostossa voit määrittää jotain, mitä ei voida määrittää moduuleilla - korvaukset - #define, kääntäjäkäskyt , keskeneräiset syntaktiset rakenteet ...
Yksinkertaistaa eri kielillä kirjoitettujen moduulien välistä vuorovaikutusta. Kääntäjälle ja linkittäjälle ei ole lainkaan väliä, onko kutsuttu moduuli kirjoitettu samalla kielellä vai toisella kielellä. Lisäksi eri kielet voivat kääntää moduulinsa samoihin objektitiedostoihin - tässä tapauksessa saat yhden linkittäjän useille kielille. Samoin on helppo tehdä kirjasto, jonka käyttäjä päättää sisällyttää projektiin CPP-tiedostoina, tallennettu valmiiksi käännettynä ja linkitetty staattisesti tai linkitetty DLL -tiedostona .
Otsikkotiedostot ovat paljon hitaampia - kääntääkseen 10 c-tiedostoa, joista jokaiseen on liitetty pitkä tiedosto, hkääntäjän täytyy käydä otsikko läpi 10 kertaa. Tämän ongelman ratkaisemiseksi monet kääntäjät käyttävät esikäännettyä .
Otsikkotiedostot yhdessä joidenkin C++-kielen objektien ( vakiot , inline-funktiot, mallit , static-muuttujat) kanssa muodostavat raskaita rakenteita.
Ohjelmoijan tulee vaihtaa funktiootsikot synkronisesti kahdessa paikassa. Jos hän muutti c-tiedostoa ja unohti tehdä saman h-tiedoston kanssa, linkki antaa epämääräisen virheilmoituksen ilman rivinumeroa. Tämä on erityisen havaittavissa C++ :ssa , jossa samalla funktiolla voi olla eri argumenttijoukko ja kääntäjätason tarkistus ei toimi. Jos ohjelmoija jätti vahingossa h-tiedoston konstruktion kesken, virhe olisi täysin eri c-tai h-tiedostossa.
C-perheen kielten projekteille on ominaista monimutkaiset projektikokoamisjärjestelmät. Loppujen lopuksi (ainakin standardissa C ++) sinun on sisällytettävä projektiin kirjasto - joko CPP-tiedostoina tai käännetyssä muodossa. Vaikka (esimerkiksi Visual C++:ssa) on esiprosessoriohjeita tätä varten, kirjasto on silti rakennettava.
C-ohjelmointikieli | |
---|---|
Kääntäjät |
|
Kirjastot | |
Erikoisuudet | |
Jotkut jälkeläiset | |
C ja muut kielet |
|
Luokka: C-ohjelmointikieli |