Méně známé skutečnosti o C a C++: Méně známá (či používaná) klíčová slova

Od Petr Zemek, 2009-07-29

Každý jazyk obsahuje určitou množinu klíčových slov a množinu rezervovaných slov (ta může být i prázdná, např. v jazyce Fortran, což má za následek možnost solidně zmást případného čtenáře zdrojového kódu :)) a programátor si časem osvojí většinu z těch, která se běžně používají (nebo nepoužívají, ale jsou nechvalně známá, např. goto). Kromě nich ale občas v jazyce existují klíčová slova méně známá, která, ať už z důvodu toho, že jejich význam pozbyl důležitosti či je většina překladačů nepodporuje, nebo se používají pouze ve speciálních případech. V tomto příspěvku bych se chtěl zaměřit na takováto klíčová slova v jazycích C a C++.

Úplný výčet klíčových a rezervovaných slov pro dané jazyky lze nalézt v příslušné normě (pro C99 je to sekce 6.4.1 a pro C++98 je to sekce 2.11). Klíčová slova rozdělím podle toho, ve kterých jazycích se vyskytují.

C99 i C++98

  • auto - klíčové slovo označující paměťovou třídu auto pro automatické proměnné. Vzhledem k tomu, že všechny lokální proměnné (i parametry funkce) patří automaticky do této paměťové třídy, tak toto klíčové slovo nemá dnes naprosto žádný význam používat. Je to pouze historická část jazyka C (v dobách dávno minulých se psalo auto int a; místo int a;), která se kvůli kompatibilitě dostala i do C++. Zajímavější to bude až v C++09, kde toto klíčové slovo dostane nový význam (bude sloužit k automatickému zjištění typu u inicializovaných proměnných pomocí typové inference).
  • register - klíčové slovo označující paměťovou třídu pro proměnné umístěné v registru. Jedná se pouze o doporučení překladači, aby danou lokální proměnnou umístil do registru. Použitím tohoto klíčové slova překladači říkáte: "Hej, překladači, já znám cílovou architekturu daleko líp než ty, takže mně tudle proměnnou prosím šoupni z důvodů optimalizace do registru". Jelikož jazyky C a C++ slouží k psání přenositelného kódu a dnešní architektury jsou velice složité, tak výsledný kód bude kvůli této zbytečné mikrooptimalizaci těžko efektivnější a proto byste toto klíčové slovo neměli používat (pouze v odůvodněných případech, např. pokud píšete kód pro nějaký jednočip, pro který máte pouze velice amatérský překladač).
  • signed - klíčové slovo, které značí, že typ dané celočíselné (nebo znakové) proměnné ma být se znaménkem. Klíčové slovo unsigned určitě znáte, protože se často používá, ale celočíselné (neznakové) proměnné jsou implicitně se znaménkem, proto se zde toto klíčové slovo neuvádí. Výjimkou jsou znakové proměnné, u kterých, pokud znaménkovost neuvedete, není normou dáno, zda bude se znaménkem nebo bez, takže zde se toto klíčové slovo může hodit.
  • volatile - modifikátor, který překladači říká, že pro přístup k dané proměnné nemá používat žádné optimalizace (např. si uložit její hodnotu do registru a pak ji používat) a její hodnotu má vždy odečítat z příslušného paměťového místa. Toto se hodí především u vestavěných systémů (čtení nějakého příznaku, který HW časem nastaví) či ve vícevláknových aplikacích. Z těchto klíčových slov se jedná o asi nejpoužívanější klíčové slovo. Poznámka pro C++: pokud chcete přidat/odstranit některé proměnné tento modifikátor, tak k tomu slouží const_cast (žádný volatile_cast neexistuje).

Pouze C99

  • restrict - modifikátor, který se používá především u parametrů funkcí typu ukazatel a slouží k usnadněním (a umožněním) optimalizací překladači. Zjednodušeně řečeno - označením ukazatele tímto modifikátorem překladači říkáme, že k objektu, na který tento ukazatel ukazuje, budeme přistupovat pouze přes tento ukazatel a ne přes jiný ukazatel. Pokud budete tento modifikátor chtít použít, pak se doporučuji podrobně seznámit s tím, co jeho použití po programátorovi vyžaduje, protože pokud toto pravidlo porušíte, pak může dojít k tomu, že překladačem vygenerovaný kód bude mít nedefinované chování. Jelikož ovšem tento modifikátor slouží pouze pro umožnění či usnadnění optimalizací, tak jej vůbec nemusíte používat (a mimo odůvodněné případy jej opravdu nedoporučuji používat). Ale hodí se vědět o tom, že v C99 něco takového je.
  • _Bool, _Complex a _Imaginary - tato trojice klíčových slov označuje datové typy pro uložení pravdivostních hodnot a komplexních čísel, které se objevily v C99 (do té doby nebyla v jazyce C přímá pdopora a muselo se to řešit explicitním zavedením vlastního typu pomocí typedef). V drtivé většině případů se s nimi v takovéto podobě nesetkáte, protože místo těchto datových typů se používají standardní typy bool z stdbool.h a complex z complex.h (ve skutečnosti se jedná o makra, která se rozvinou v příslušný datový typ s podtržítkem na začátku). Kód je pak přehlednější. Pokud přemýšlíte nad tím, proč se tyto datové typy jmenují zrovna takto divně, tak důvodem byla zřejmě snaha o zachování kompatibility s kódem, ve kterém jsou tyto typy definovány programátorem.

Pouze C++98

  • asm - tato deklarace (někdy nazývána příkaz) se používá ve tvaru asm(string-literal); a má implementačně závislý význam. Již z tohoto vyplývá, že použití této deklarace není přenositelné (hodí se tedy pouze v odůvodněných případech). Ve většině implementací slouží k vložení kódu v jazyce symbolických instrukcí (assembler) přímo do zdrojového kódu. Detaily je vždy třeba hledat ve specifikaci k příslušnému překladači. Poznámka: v implementacích se lze setkat i s tvarem asm { statements }, který ale není standardní.
  • export - toto klíčové slovo umožňuje oddělit deklaraci šablony od její implementace. Jak poznamenal dr. Peringer od nás z fakulty, tak toto klíčové slovo se hodí pro komerční firmy, kterým vadí "nucený open-source" jejich kódu, který poskytuje šablony :) (ve skutečnosti to tento problém tak úplně neřeší, viz detaily v uvedených článcích dále). Vešlo ve známost jako klíčové slovo, které má nejmenší podporu v překladačích (drtivá většina překladačů jej neimplementuje, včetně gcc, kvůli náročnosti implementace a/nebo kvůli tomu, že toho ve skutečnosti moc nepřináší), takže se s ním téměř nesetkáte. A jelikož se s ním nesetkáte, tak to nemá cenu rozpitvávat. Pokud by vás zajímaly detaily o tom, co ve skutečnosti export znamená a jaké zde existují problémy, tak vřele doporučuji tento a tento článek od Herba Suttera.
  • mutable - klíčové slovo označující paměťovou třídu pro tzv. "měnitelné" proměnné. Používá se u nestatických datových složek objektů, které mohou být měněny i u konstantních objektů. Toto klíčové slovo se používá opravdu pouze ve speciálních případech, kdy opravdu potřebujete měnit některou složku konstantních objektů (já jsem to využil pouze jedenkrát). Pokud jej chcete použít, tak se raději třikrát zamyslete, protože ve většině běžných případů to značí pouze chybu v návrhu.
  • wchar_t - datový typ pro tzv. "široké znaky" (wide characters), které nelze zakódovat na 8 bitech (Unicode). V C99 se vyskytuje jako typedef nad některým existujícím typem, ale v C++ se jedná o vestavěný datový typ. Používá se především v aplikacích, které obsahují podporu pro více jazyků nebo pro aplikace s asijským textem, který obsahuje tolik různých znaků, že by se všechny nevešly do jednoho charu :).
Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
3 + 0 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.