Kompilátory jazyka C existují snad pro všechny počítače a operační systémy, většinou ve více verzích. Přesný postup kompilace závisí jak na počítači, tak na operačním systému, i na variantě kompilátoru. Popíšeme nyní implementaci kompilátoru cc Unixu.
Kompilátor cc (c-compiler) rozeznává několik typů souborů a vyžaduje jejich rozlišení smluvenými příponami jmen (čl. 2.2):
Přípona | Typ souboru |
.c | zdrojový program v jazyce C |
.h | hlavičkový soubor pro #include |
.i | zdrojový program zpracovaný makroprocesorem |
.s | program v asembleru |
.o | sestavovaný modul programu |
Program cc v závislosti na požadavcích uživatele vyvolává další programy - součásti kompilátoru. Jsou to makroprocesor, kompilátor (s částí pro analýzu, částí pro generování kódu a volitelným optimalizátorem kódu), asembler a konečně sestavující program (obr. 5.3).
Příkazem pro shell
$ cc prog.c $
$ a.out $
main() { #ifdef ENGLISH printf("Good morning!\n"); #else printf("Dobry den!\n"); #endif }
Kompilátoru lze však zadat řadu voleb, klíčů. Některé z nich způsobí, že se kompilace neprovede úplně, ale skončí v některé fázi. Tak např. klíčem -t si uživatel vyžádá, aby zdrojový text zpracoval jen makroprocesor a výsledek zanechal v souboru prog.i.
Jiné klíče jsou určeny pro sestavující program. Např. -o jméno udává jméno souboru, do něhož bude uložen výkonný program (místo a.out).
Klíčem -D můžeme v etapě kompilace definovat identifikátor; tak např. aktivací kompilátoru
$ cc -DENGLISH -t pozdrav.c $
main() { printf("Good morning!\n"); }
Příkazem
$ cc -o pozdrav pozdrav.c $
$ pozdrav Dobry den! $
Vstupem do každé fáze činnosti kompilátoru může být více souborů. Kompilátor podle přípon jejich jmen pro každý soubor zvolí část kompilátoru, v níž má zpracování souboru zahájit. Začne pak jednotlivé části kompilátoru provádět. Není-li řečeno jinak, vytváří v pracovním adresáři soubor a.out s výkonným programem. Je-li rozsáhlejší program vytvářen z více částí, je nejlepší uchovávat všechny jeho části (a jen je) v jediném adresáři. V kontextu tohoto adresáře lze pak jediným příkazem
$ cc *.c $
Sestavující program je součástí operačního systému, nikoliv jazyka. Přesto má vliv na programy psané v jazyku C. Platí to zejména o jménech externích objektů (funkcí), která musí vyhovovat konvencím použitého sestavujícího programu. Jde např. o počet znaků identifikátorů a možnost rozlišit mezi velkými a malými písmeny.
Výsledek sestavení, tj. výkonný program, silně závisí na operačním systému. Rovněž způsob předání argumentů, zadávaných při aktivaci programu, se bude v různých systémech lišit. Předávání argumentů v Unixu ukážeme na příkladě programu příkazu echo. Tento příkaz na terminálu opisuje zadané argumenty. Program echo v jazyku C pro Unix může vypadat např. takto:
main(argc, argv) int argc; char *argv[]; { while(--argc) printf("%s%c", *++argv, (argc>1)?' ':'\n'); }
V proměnné argc program echo obdrží počet argumentů příkazu, argv je pole ukazatelů na řetězce argumentů. Argument číslo nula vždy podle konvence obsahuje jméno příkazu, tedy argc je vždy alespoň 1. Pro aktivaci
$ echo abcd xyz abcd xyz $