GNU C
-=-=-=-
while (*p++ = *q++);
-- Dennis M. Ritchie
Většina lidí čte název Borland C compiler jako překladač jazyka
C od Borlandu. Martin Mareš si myslí, že tomu tak není a že je třeba
název jinak ozávorkovat a ve skutečnosti to je překladač Borland C,
kde Borland C je jazyk, jehož syntax není dopusud známa.
O GNU C compileru platí to samé. Syntax GNU C ale známa je a ví
se o ní, že to je nadmnožina Ansi C a má některé užitečné rošíření,
které se hodí hlavně, když chcete mít program hodně rychlý.
Inline funkce versus builtiny
Jazyk C se kompiluje jen do malé podmnožiny instrukcí počítače.
Standard říká, že ostatní (jako třeba in, out, nebo nová skvělá sada
MMX :) jsou příliš závislé na architektuře, než aby se dávaly do
jazyka a jediná správná cesta je volat je z knihovních funkcí, které
jsou psané v assembleru.
Bohužel často se tyto funkce používají ke zrychlení výsledku.
Existuje například mnoho chytrých cest, jak kopírovat paměť (rep
movsb na xt-286, po 32bitových blocích na 386-486, přes koprocesor
na pentiu..), které ani ten nejchytřejší překladač z jednoduchého
for cyklu nevymyslí. Nebo jsou situace, kdy takové instrukce musíte
používat často (třeba out a in v hardwarových driverech) a jejich
volání jako funkcí zdržuje, zvětšuje kód a přináší další potíže.
Jedna odpověď na to je built-in. Do překladače se zaintegrují
nejčastější takové případy (jako je memset, outb...) a ten potom umí
sám generovat optímální kód. Takových funkci je hodně (koukněte se
do string.h a math.h například sin, cos, abd, fabs, strcpy, strdup,
memcpy, memmove a takhle bych mohl pokračovat ještě hodně dlouho)
řádově se to pohybuje podle mého názoru ve stovkách. Jednotlivé
překladače se často triumfují v tom, kdo má více takových funkcí
integrovaných, a některé - jako třeba Watcom C - jich umí opravdu
hodně.
Na druhou stranu je to jenom jakási ošklivá výpomoc, která
funguje jen v nejčastějších připadech. Představte si třeba, že jste
vymysleli bezvadnou cestu jak implementovat násobení ve fixedpointu
a chcete to použít ve svých programech. V knihovně taková funkce ale
není a tak ani compiler ji nemá jako builtin. A máte smůlu. Takových
případů jsou doslova tisíce - například memset pro 16ti a 32
bitová čísla, který se hodí pro truecolor apod. Navíc se to rozchází
s filozofií C jako minimálního ale maximálně rychlého jazyka.
V GCC vývojáři zvolili jinou cestu. Builtin je opravdu jenom
několik základních funkcí (abort, abs, alloca, cos, exit, fabs, ffs,
labs, memcmp, memcpy, sin, sqrt, strcmp, strcpy, strlen) a to hlavně
proto, že jsou natolik časté, že je třeba nejenom generovat
optimální kód bez callu ale třeba i předpočítávat jejich výsledek
pro konstantu a dělat další podobné optimalizace specifické pro
danou funkci. Místo toho ale do GCC přidali několik rozšíření tak,
aby běžný programátor, aniž by hackoval překladač, si mohl vytvořit
svoje vlatsní funkce, které se chovají jako builtin.Tyto rozšíření
jsou ale navíc tak obecné a šikovné, že se používají i v mnoha
jiných případech. Je to:
* Rozšířená syntaxe asm
* extern inline funkce stejně rychlé jako makra
* __builtin_constant_p
* atributy funkcí
Tak to je asi to nejdůležitější. S těmito rozšířeními jde
implementovat celkem dost věcí. Abyste měli co studovat, ještě
přidám inline verzi string.h a math.h. Ty můžete includovat i do
vlastních programů, pokud chcete, aby na x86 běžely rychleji.
Rozšížení šikovná hlavně pro optimalizaci
Když se tak dívám, co všechno jsem už napsal a popsal jenom
čtyři tak z cca 80 rozšížení, vezmu to už jenom krátce a neúplně.
* Rozšíření (nejenom) pro psaní maker
* Explicitní určování regitrů pro proměné
Ostatní
Gcc má mnoho dalších rozšížení jako je například aritmetika s
labely a ukazately na funkce, goto *ukazatel, intervaly pro case
(case 1 ... 9:), long long (64 bit integer), long double (jako
extended v Pascalu), vnořené funkce (jako v Pascalu), atributy pro
proměné a typy určující zarovnávání, pakování struktur apod,
konstrukce volání funkce parametr po parametru, // komentáře a mnoho
dalších více či méně užitečných věcí. Možná o nich jednou také
napíšu.
výheň