A C vagy a cpp előfeldolgozó biztosítja a C és C ++ programozási nyelveken írt számítógépes programok fordításának ( összeállításának ) előzetes szakaszát . Ennek előfeldolgozó , ez elsősorban lehetővé teszi a felvétel egy szegmensének forráskód egy másik fájlban ( header vagy header fájlok ), a helyettesítési karakterlánc ( makró definíció ), valamint a feltételes fordítási .
Sok esetben ez egy olyan program, amely el van különítve a fordítótól, és amelyet ez utóbbi hív meg a fordítás elején. Az előfeldolgozó direktívákhoz használt nyelv független a C nyelv szintaxisától , így a C előfeldolgozó külön használható más típusú forrásfájlok feldolgozásához.
Az előfeldolgozó gondoskodik a C szabvány első négy (nyolcból) fordítási szakaszáról :
A C előfeldolgozó leggyakoribb használata az irányelv:
#include <…>akinek feladata egy fájl tartalmának átmásolása az aktuális fájlba. Általában könyvtárfejlécek , például matematikai függvények ( #include <math.h> ) vagy standard bemeneti / kimeneti függvények ( #include <stdio.h> ) beillesztésére szolgál .
Az alábbi példában az " #include <stdio.h> " irányelv helyébe az stdio.h fájl szövege lép .
#include <stdio.h> int main(void) { printf("Bonjour le monde!\n"); return 0; }Ezt az irányelvet dupla idézőjelek ( " ") segítségével is meg lehet írni #include "stdio.h". Ha a fájlnév a szögletes zárójelek közé esik ( < >), akkor a fájlt egy szabványos fordító által ismert útvonalakban keresik (más néven include path-ok ). Ha a fájl nevét dupla idézőjelek veszik körül, az aktuális könyvtár hozzáadódik az összes fájlkeresési út elé; a keresés ezért az aktuális könyvtárral kezdődik, mielőtt folytatná a keresési útvonalakat. A C fordító és a fejlesztői környezetek általában lehetővé teszik a programozó számára, hogy felvegye azokat a könyvtárakat, ahol a fájlok megtalálhatók.
Megállapodás szerint a felvenni kívánt fájlok kiterjesztése ".h" (vagy .hpp a C ++ nyelven), a nem feltüntetendő fájlok kiterjesztése pedig ".c" (vagy ".cpp" kiterjesztésű a C ++ fájlban) . Ezt azonban nem kell betartani. Alkalmanként más kiterjesztésű fájlok is szerepelnek benne: a .def kiterjesztésű fájlok többször is felvenni kívánt fájlokat jelölhetnek, minden egyes alkalommal kiterjesztve a tartalmat, így az #include "icon.xbm" egy XBM képfájlra vonatkozik (amely ugyanakkor egy C fájl).
A #include irányelv gyakran tartalmaz úgynevezett #include őröket vagy a #pragma irányelvet a kettős befogadás elkerülése érdekében.
Az iránymutatások #if, #ifdef, #ifndef, #else, #elifés #endiffel lehet használni a feltételes fordításra.
#if VERBOSE >= 2 printf("Hello world!"); #endifA legtöbb Microsoft Windows fordító implicit módon meghatározza _WIN32. Ez lehetővé teszi, hogy a kód, beleértve az előfeldolgozó parancsokat is, csak akkor fordítson fordítást, amikor a Windows operációs rendszereket célozza. Néhány fordító definiálja WIN32helyette. Azok a fordítók, amelyek nem implicit módon definiálják a makrót _WIN32, megadhatók a fordító parancssorában a -D_WIN32.
#ifdef __unix__ // __unix__ est souvent défini par les compilateurs pour des systèmes Unix # include <unistd.h> #elif defined _WIN32 // _Win32 est souvent défini par les compilateurs pour des systèmes Windows 32 ou 64 bit # include <windows.h> #endifEz a kódpélda teszteli, hogy a makró __unix__definiálva van-e. Ha igen, a fájl <unistd.h>benne van. Ellenkező esetben teszteli, hogy a makró _WIN32definiálva van-e, ebben az esetben a fájl <windows.h>szerepel.
Lehetséges operátorok használata az irányelvvel #if, például:
#if !(defined __LP64__ || defined __LLP64__) || defined _WIN32 && !defined _WIN64 // compilation pour un système 32-bit #else // compilation pour un système 64-bit #endifA legtöbb modern programozási nyelv nem használja ezeket a szolgáltatásokat, és inkább a szokásos, ha ... akkor ... más ... operátorok használatára hagyatkozik , a fordítóra bízva a felesleges kód eltávolítását.
A makromechanizmust gyakran használják a C-ben, hogy meghatározzanak olyan kis kódrészleteket, amelyeket a program különböző helyein újra felhasználnak. Az előprocesszor végrehajtása során a makró minden egyes hívását a fájl törzsében ennek a makrónak a definíciója váltja fel.
Az objektum és a függvény típusú helyettesítő makró deklarálásának általános szintaxisa:
#define <identifiant> <contenu de remplacement> // type objet #define <identifiant>(<liste des paramètres>) <contenu de remplacement> // type fonction avec paramètresA függvény típusú makrók nem tartalmazhatnak szóközt az azonosító és a nyitó zárójel között.
Példa egy objektumtípusú makróra:
#define PI 3.14159amely meghatározza a PI makrót (azonosítót), amely a 3.14159 (helyettesítő tartalom) értéket veszi fel. Ezt a makrót úgy hívhatjuk, mint bármelyik C függvényt, így az előprocesszor áthaladása után kettős z = PI; helyére kettős z = 3,14159 lép ;
Példa egy függvénytípus makróra:
#define MAX(a,b) a>b?a:bmeghatározza a MAX makrót (azonosítót), figyelembe véve 2 paramétert (a és b) és kiszámítva a> b? a: b (helyettesítő tartalmat). Ezt a makrót ugyanúgy hívhatjuk, mint bármely más C függvényt, így az előprocesszor áthaladása után z = MAX (x, y); helyébe a következő lép: z = x> y? x: y;
A makróknak ez a használata alapvető fontosságú a C-ben, különösen a biztonságos adatstruktúrák meghatározása vagy hibakereső eszközként, azonban lelassíthatja az összeállítást és néha a végrehajtást, és számos buktatót jelent. Tehát, ha f és g két függvény, akkor z = MAX (f (), g ()); helyébe a következő lép: z = (f ()> g ()) a f (): g (); . Ez a parancs megköveteli a két funkció egyikének kétszeri értékelését, ami lelassítja a kódot.
Ne feledje azt is, hogy a makró definícióját törölni lehet az "#undef" irányelvvel:
#undef <identifiant>A ## operátor kiküszöböli a körülötte lévő összes teret (vagy üres helyet ), és két tokent (vagy tokent) összefűz (összeállít). Ezt új tokenek létrehozására használják, és csak makrókban használhatók, például:
#define ma_macro(x) x ## _suffixefelváltja
ma_macro(identifiant);keresztül
identifiant_suffixe;A #error irányelv üzenetet ad a hibaüzenetfolyamhoz.
#error "message d'erreur"Így ezek az irányelvek felhasználhatók például fordítási hiba létrehozására:
#if RUBY_VERSION == 190 #error 1.9.0 not supported #endifA #pragma irányelv egy fordítóspecifikus irányelv. Ezt az irányelvet gyakran használják bizonyos hibaüzenetek elnyomásának engedélyezésére vagy a verem vagy a hibakereső halom kezelésére.
A C (C99) szabvány 1999-es verziója a #pragma irányelvek sorozatát vezeti be , például a #pragma STDC-t a numerikus pontosság ellenőrzésére.
Riasztási üzenetekSzámos megvalósítás (beleértve a GNU, az Intel, a Microsoft és az IBM C fordítóit) egy nem szabványos irányelvet biztosít a figyelmeztető üzenetek megjelenítéséhez a kimenetben a fordítás leállítása nélkül. Az ilyen típusú irányelvek gyakori használata annak megakadályozása, hogy a kód egy része "elavult" legyen (nagyon elterjedt fordítási hiba az elavultnál, ami azt jelenti, hogy "elavult"):
Az irányelv kifejezés az előfeldolgozó által feldolgozandó forráskód soraira utal (pl. #Define vagy #include). Kiterjesztéssel az előprocesszornak szánt utasítás vagy makrodefiníció kijelölésére szolgál.
A GNU Cppi eszköz célja az előfeldolgozó direktívák helyes behúzása , hogy tükrözze azok fészkelését, és biztosítja, hogy minden #if, #elif, #define irányelv és a következő token között pontosan egy hely legyen, és végül az eredményt írja a kimenetre . A "#" karakter és a következő irányelv közötti szóköznek meg kell egyeznie az irányelv fészkelési szintjével (lásd még a Wikikönyvek cppi könyvét ). Ez egy GNU csomag, amelyet Jim Meyering tart fenn , és a GNU General Public License feltételei szerint terjesztenek .