Překlad programu

[  Základní pojmy   Překladač GCC  |  Překlad s knihovnou <math.h>  |  Překlad programu  |  Přepínače kontrolující výstup  |  Volba dialektu jazyka C/C++  |  Informace pro debugger, optimalizace  |  Varování, chyby  ]

Základní pojmy

Protože předpokládám, že někteří čtenáři s nástroji pro překlad programů nikdy nepracovali, musíme si vysvětlit pár základních pojmů. Pokud tyto pojmy znáte, můžete je přeskočit a pokračovat částí o použití překladače GCC.

Překladač, kompilátor, anglicky compiler
je program, který vezme zdrojový text programu a přeloží jej do jazyka stroje, což jsou obvykle kódy instrukcí pro daný procesor. Výsledkem tohoto překladu obvykle není spustitelný program, protože v místech kde se volají podprogramy z jiných modulů a knihoven, nejsou konkrétní adresy těchto podprogramů, ale pouze značky, které se zpracují později při linkování. Souborům, které produkuje překladač se říká objektové soubory (nemá to nic společného s objektově orientovaným programováním). Důležitou funkcí překladače je syntaktická kontrola.
Sestavovací program, linker
slouží k sestavení samostatně přeložených modulů a knihoven do funkčního celku. Linker do kódu doplní konkrétní adresy podprogramů (statický překlad) nebo kód pro jejich zavolání (při použití dynamických knihoven). Pokud vytváříme spustitelný program (u knihoven to je trochu jinak), linker nakonec doplní do programu kód, který se používá při spuštění programu. Tato část, stejně jako formát použitých statických nebo dynamických knihoven se liší v závislosti na použitém operačním systému a hardwarové platformě. Pokud proto chceme vyrobit spustitelný program pro jinou platformu, musíme u jazyků typu C, C++ provést překlad na zvolené platformě znovu.
Debugger
je program pro ladění a hledání chyb v programu. Aby mělo ladění s debuggerem smysl, je obvykle nutné říci překladači, aby do výsledného kódu přidal speciální značky, díky nimž si debugger bude umět spojit konkrétní část binárního kódu programu s konkrétními řádky zdrojového textu.
Preprocessor
je speciální program používaný v jazycích C a C++ pro zpracovávání maker a symbolických konstant. Tento program v podstatě provádí pouze textové náhrady definovaných symbolů v textu a umožnuje podmíněný překlad. Příkazy pro preprocessor začínají vždy znakem mřížky (#), například #define nebo #ifndef. Příkazy preprocessoru byste, alespoň zpočátku, měli používat co nejméně.
Assembler
je program pro překlad jazyka symbolických instrukcí do binárního kódu. Někdy bývá nesprávně zaměňován se samotným jazykem symbolických instrukcí, což je vemi nízkoúrovňový jazyk, kde zdrojový kód tvoří posloupnost zkratek instrukcí procesoru. Při velmi speciálních příležitostech lze jazyk symbolických instrukcí kombinovat s kódem v jazyce C. Velmi speciální situace zahrnují přístup k nejnižsím úrovním hardwaru a brutální optimalizace. Při běžném programování se s tím nesetkáte (a ani by to většinou nebylo prospěšné).
Syntaktická chyba
je prohřešek proti gramatice programovacího jazyka. Počítač je matematický stroj a vyžaduje naprosto jednoznačný předpis své činnosti. Ve zdrojovém kódu nesmí být žádné syntaktické chyby, aby bylo jednoznačné, co má překladač dělat. Překladač neví, co chcete naprogramovat, proto se nemůže ani pokoušet o opravu vašich chyb, to musíte udělat sami. Mezi syntaktické chyby patří především překlepy, ale může to být také použití nekompatibilních datových typů nebo třeba chybné použití operátorů (např. nemůžete zkoušet násobit textové řetězce).
Sémantická chyba
je chyba v logice vašeho programu. Váš program může být syntakticky správný, překladač jej přeloží, linker slinkuje, ale program přesto může fungovat chybně. Za tyto chyby je vždy zodpovědný programátor a je na něm, aby se jich zbavil. Tyto chyby překladač ani linker neodhalí. Pokud máte štěstí, může na ně překladač nepřímo upozornit pomocí varovných hlášení při překladu.
Chybové hlášení
je zpráva, kterou vám překladač nebo linker sdělují, proč nelze z vašeho kódu vytvořit spustitelný program. Tato zpráva obvykle obsahuje jméno souboru a číslo řádku, kde se chyba nachází. Pozor! V jazyce C může někdy překladač odhalit chybu na jiném řádku, než je skutečná příčina. Pokud se vám označené číslo řádku nezdá, zkuste hledat chybu i několik řádků okolo. Abyste mohli co nejlépe lokalizovat své chyby, pište na každý řádek zdrojového textu maximálně jeden příkaz. Usnadníte si tím nejen lokalizaci chyb, ale i ladění. Chybové hlášení obsahuje také vysvětlení, co je podle překladače špatně.
Varovné hlášení
je upozornění, kterým vám překladač nebo linker dávají najevo, že váš program sice možná jde přeložit, ale že obsahuje podezřelé konstrukce, které mohou naznačovat závažnější problém. Moudrý programátor věnuje varovným hlášením překladače náležitou pozornost. Vaší ambicí by měl být překlad bez varovných hlášení. Dobré porozumění chybovým hlášením vyžaduje znalost angličtiny a především dobrou znalost fungování počítače a logiky programovacího jazyka. Pokud zatím tyto znalosti nemáte, nezoufejte. Není tak těžké se to naučit. Čím více budete programovat, tím to pro vás bude snazší.

Překladač GCC

GCC znamená GNU Compiler Collection. Jak název napovídá, jde o kolekci programů určených pro překlad programů napsaných v různých jazycích. V současné verzi (3.4) je podporováno několik programovacích jazyků (C, C++, Objective C, assembler, Ada, Java, Fortran77). Primárně je však tento překladač určen pro překlad jazyků C, C++ a Assembleru. Tento překladač funguje v současné době na většině hlavních platforem (Unix, Windows, MacOS; Intel, PPC, Sparc, různé jednočipy, a jiné).

Nejdůležitějšími programy jsou překladač, preprocesor, assembler a sestavovací program (linker). Člověk však naštěstí nemusí znát konkrétní jména těchto programů. Stačí volat pouze překladač (gcc pro jazyk C, g++ pro jazyk C++) a ten potom podle použitých parametrů zavolá ty správné programy ve správném pořadí.

Překlad programu

Předpokládejme, že jste napsali klasický program Hello world a uložili jej do souboru helloworld.c

#include <stdio.h>

int main(void)
{
  printf("Tě péro sombréro!\n");
  return 0;
}

Z příkazové řádky tento soubor přeložíme následujícím příkazem:

$ gcc helloworld.c

Překladač vytvoří spustitelný soubor a.out, který po spuštění vypíše text:

$ ./a.out
Tě péro sombréro!
$

Při tomto způsobu překladu jsme ponechali implicitní nastavení překladače. Není ovšem dobré spoléhat na standardní nastavení. Překladač v tomto stavu nehlídá všechny chyby, které by se v programu mohly vyskytnout. Zvláště začátečníci by měli překládat programy s poněkud přísnějším nastavením. Překladač potom bude vypisovat více varovných zpráv. Může se to sice zdát otravné, ale uvažte, že čím více chyb odhalí překladač už při překladu, tím více práce to ušetří při ladění.

$ gcc -std=c99 -Wall -pedantic -g helloworld.c -o hello

S tímto nastavením se budou překládat všechny projekty předmětu IZP. Pokud chcete překládat s ještě přísnějším nastavením, zkuste toto:

$ gcc -std=c99 -Wall -Werror -pedantic-errors -g helloworld.c -o hello

V prostředí Windows se překladač používá stejným způsobem. Rozdíl je v tom, že prostředí Windows není case-sensitive, takže je jedno, jestli soubory pojmenováváme velkými nebo malými písmeny. Aby byly programy přenositelné, je dobré si zvyknout pojmenovávat je výhradně malými písmeny. Vyhnete se tím případným problémům při přenosu programu do prostředí Linuxu.

Překlad s knihovnou <math.h>

Při překladu programu, který používá matematické funkce z math.h je nutné při překladu přidat přepínač -lm, který zajistí přilinkování matematické knihovny. Bez této knihovny sice půjde program přeložit, ale nepůjde jej slinkovat.

$ gcc -std=c99 -Wall -pedantic -g -lm matematika.c -o matematika

Používání knihoven je podrobněji probíráno v kapitole Moduly a knihovny.

$ gcc -std=c99 -Wall -pedantic -g -lm matematika.c -o matematika

Přepínače kontrolující výstup

Parametr Význam Poznámka
-c Pouze zkompiluje zdrojový soubor, ale neprovede linkování. Tento přepínač se používá při odděleném překladu více zdrojových souborů. Je možné jej použít pro syntaktickou kontrolu zdrojového souboru - je to pak rychlejší, protože se neprovádí kompilace, překladač pouze vypíše chyby a varovné zprávy.
-o soubor Uloží výstup do spustitelného souboru daného jména. Bez tohoto přepínače překladač vytváří soubor, který se jmenuje a.out (Linux) nebo a.exe (Windows).  
-E Překlad se zastaví po zavolání preprocesoru. Toto je užitečné, když se chcete podívat, zda se správně rozgenerovala makra.  
-S Překlad se zastaví po vygenerování kódu pro assembler. Toto používají zvrhlíci, které baví rochnit se ve změti instrukcí. Občas je možné ručně změnit pár instrukcí v rámci optimalizací, ale většinou assemblerový kód využijete tehdy, když chcete před někým dělat machra. ;-) Pozor! Pokud se vám pomocí tohoto povede sbalit životní partnerku, vystavujete se nebezpečí, že vaše děti budou mít ve škole přezdívky jako šprt, integrál nebo EAX!
-v Vypíše parametry, se kterými byl překladač sám přeložen, plus jeho verzi. Z těchto údajů se dají vyčíst zajímavé údaje, jako kde překladač očekává statické, či dynamické knihovny, nebo jestli zvládá vícevláknové aplikace. Podobnou funkci má i přepínač -###. Podrobnosti viz manuálovou stránku gcc.
--version Vypíše verzi překladače.  

Volba dialektu jazyka C/C++

Přepínač Popis Poznámka
-std=c99 Zapíná specifikaci jazyka C podle normy ISO z roku 1999. Tento přepínač rozhodně používejte! Zajistíte tím, že program bude přenositelný mezi moderními překladači na množství platforem a vyhnete se nechtěnému použití nestandardních rozšíření překladače GCC.
-std=c++98 Zapíná specifikaci jazyka C++ podle normy ISO z roku 1998. Pouze pro jazyk C++. Nepoužívat u Céčkových programů!
-ansi Zapíná specifikaci jazyka C podle normy ANSI. Tento přepínač je ekvivalentní přepínači -std=c89. Raději používejte -std=c99. Tento přepínač je použitelný, když chceme, aby byl program kompatibilní se starší verzí překladače.

Informace pro debugger, optimalizace

Parametr Význam Poznámka
-g, -g1, -g2, -g3 Překladač bude do výsledného kódu přidávat pomocné ladící informace pro debugger. Pokud při překladu není zvolen nějaký z těchto přepínačů, bude debugger schopen zobrazovat pouze informace na úrovni assembleru - nebude schopen zobrazovat názvy funkcí a proměnných. Číslo za přepínačem udává, jak podrobné ladící informace se budou generovat. Přepínač -g je ekvivalentní přepínači -g2. Tyto přepínače lze použít zároveň s přepínačem -O, ale většinou to nemá smysl. U starších verzí překladače to může působit potíže.
-ggdb, -ggdb1,
-ggdb2, -ggdb3
Podobné jako u přepínače -g, ale ladící informace budou optimalizovány pro debugger gdbg. Existují i jiné přepínače, kterými se dá zapnout optimalizace pro jiné debuggery, ale gdb je nejběžnější. Více viz manuálovou stránku gcc.
-O, -O1, -O2, -O3 Zapne optimalizaci výsledného kódu. Číslo za přepínačem specifikuje úroveň optimalizace. Přepínače -O a -O1 jsou ekvivalentní. Čím vyšší úroveň optimalizace zvolíte, tím delší dobu bude trvat překlad. Zvláště na pomalých strojích je vhodné zapínat optimalizace pouze při konečné kompilaci, ne při běžném psaní kódu. (Platí pro jednoduché projekty.) Tento přepínač používejte společně s přepínačem -g jenom když víte co děláte.
-Os Zapne optimalizaci kódu zaměřenou na velikost výsledného souboru. V podstatě zapne všechny optimalizace -O2, které nemají za následek zvětšení výsledného kódu, plus přidá některé další optimalizace. Používá se výjimečně
-O0 Vypne optimalizace. Tento přepínač je implicitně zapnut.  
-p, -pg Překladač bude do výsledného kódu přidávat informace použitelné pro profilovací analýzu programem prof nebo gprof (pro -pg). Profilování je statistická analýza běhu programu, ze které se dá zjistit, ve které funkci program tráví nejvíce času. Pokud vás svrbí prsty a rádi byste svůj program optimalizovali, nejprve proveďte profilovací analýzu. Optimalizovat funkci, která se vyvolá dvakrát během celého běhu programu, je mrhání vaším časem. Tento parametr je nutné použít i při linkování.

Varování, chyby

Parametr Význam Poznámka
-Wall Zapíná produkci varovných zpráv pro téměř všechny aspekty, které překladač umožňuje hlídat. Existuje velké množství parametrů -W..., které dovolují určovat konkrétní aspekty jazyka, které má překladač hlídat. Existují aspekty, které se pomocí -Wall nezapnou, ale ty se týkají výhradně jazyka C++. Velmi důležité pokud se chceme vyhnout množství nepříjemných chyb.
-pedantic Hlídá, jestli program striktně dodržuje normu ISO C nebo ISO C++ zadanou parametrem -std. Pokud program normu nedodržuje, vypisuje se varování. Velmi důležité pro psaní přenositelných programů.
-Wextra, -W Produkuje některá další užitečná varování. Zapnutím tohoto přepínače přinutíme překladač, aby prováděl (částečnou) sémantickou kontrolu kódu.
Přepínač -W je zastaralý. Nový název přepínače -Wextra je výstižnější a nehrozí jeho záměna s přepínačem -w.
 
-w Potlačí veškeré varovné zprávy. Pozor! Má naprosto jinou funkci než přepínač -W (velké písmeno), snadno se s ním plete a může způsobovat falešný pocit, že překládaný program je v naprostém pořádku.
-Werror Všechna varování interpretuje jako chyby. Pro začátečníky je velmi užitečné mít jej zapnutý.
-pedantic-errors Jako -pedantic, ale místo varování produkuje rovnou chyby. Pro začátečníky je velmi užitečné mít jej zapnutý.
Zdá se, že některé implementace GCC pod Windows používají v hlavičkových souborech nestandardní rozšíření, takže tento přepínač zde nejde použít.

Autor: David Martinek. Poslední modifikace: 9. October 2011. Pokud v tomto dokumentu narazíte na chybu, dejte mi prosím vědět.