Hezký článek ;) Pro zajímavost také stojí za to si přečíst blog jednoho z vývojářů Librsvg (URL zrovna po ruce nemám - viz google). Postupně přepisují knihovnu z C do Rustu, ovšem po částech, takže interoperabilita mezi oběma jazyky (oběma směry) je pro ně zásadně důležitá.
Jinak drobnost: pokud se nepletu (ale možná ano), tak typy uint8_t, uint32_t apod. jsou teprve od C99, takže pozor na volby překladače.
hmm mohl jsem to vlastne dat do clanku, tak aspon tady:
http://en.cppreference.com/w/c/types/integer
Jen bych dodal, pozor na to. Je fajn a vhodné používat ty základní rozšířené, ty pro přesnou velikost.
Ale třeba pro "int_fast8_t" na to překladače dost kašlou a bývá zhusta definován jako char / signed char, přičemž klasické int bývá rychlejší a často i lépe optimalizované (na asemblerovské úrovni), protože int mívá rozměr registru, kdežto char nuluje a bere ohledy na horní bity.
Typicky for(int i=80;i;i--) na tom bývá lépe jak do velikosti kódu tak i rychlosti, než ... int_fast8_t i=80 ...
Schválně jsem zkusil kompilovat smyčku s čítačem jako int, int8_t a int_fast_t. GCC, přinejmenším verze 6.3 v Ubuntu zesty, na to kašle totálně, ve všech případech použije 32bitový registr (int je defaultně 32 bitů i na amd64) a s nějakým extra nulováním vyšších bajtů se nepárá. Jediný rozdíl je, když bude podmínka řekněmě i<300, což je u int8 evidentně pravda vždycky, tak z toho GCC udělá nekonečnou smyčku bez podmínky, ale pokud se hodnota i uvnitř smyčky ještě k něčemu používá, tak ji tentokrát (a jen tentokrát) ještě šoupne do jiného registru pomocí movsbl de facto jako rychlé mod 256.
Tak u lokálních proměnných a čítačů cyklů je to skoro jedno, tam je kompilátor schopen klidně počítat v opačném pořadí, unrollovat atd. Spíš bych řekl, že to má význam u proměnných ve strukturách, některé procesory (Alpha v prvních verzích) například neuměly číst z paměti 16 bitů apod. Takže int_fast16_t mohl být násobně rychlejší než int16_t.
Pokud jsem pochopil, tak int_fast16_t je rozšíření int_least16_t
Takže, opravdu správně by měl int_fast použít velikost takovou, jaká bude mít po překladu nejrychlejší běh, i právě s ohledem na zarovnávání. Prostě takové rychlé auto s definicí minimální velikost.
Kdežto int_least16_t není nutně vhodné pro zarovnání. Jen že má mít minimálně 16 bit a více _jen_ když je to nutné, pokud procesor s 16bit pracovat nedokáže.
Alespoň tak to chápu já.
Pokud vím, tak ne, typy jako u32, u64 apod. mají povinně stanovenou délku (resp. nemůzou být delší) a u indexů, všelijakých čítačů apod. se zase vynucuje usize (popř. isize). Je to rigidnější, na druhou stranu nevím, jestli je int_fast* doopravdy užitečná věc. Pozor - neříkám nutně, že není, spíš by mě zajímal nějaký takový příklad.
int_fast je zatím dost neužitečné, tím že není bráno vážně - není momentálně primitivním typem, ale jen typedef. Tedy pokud vůbec je.
Hodívalo by se nám při low-level, v (našich) obecných knihovnách. Ale vypadá to, že stoupá výpočetní výkon (přestože to teď jde pomaleji) natolik, že než se stačí "fast" reálně implementovat, bude outdated. :-( Ale třeba překvapí. A třeba časem budou obdobné problémy pro 128, 64 kontra 32, jako bývaly mezi 32(64) kontra 8.
Ale ten "fastX" princip je mi sympatický.