Jak pracovat s proměnnými, datovými typy a aritmetickými výrazy v programovacím jazyce C

Jazyk C nabízí bohatou škálu matematických operátorů, které můžete používat k manipulaci s daty. V této kapitole z knihy Programování v jazyce C, 4. vydání se Stephen G. Kochan zabývá datovými typy int, float, double, char a _Bool, úpravou datových typů pomocí short, long a long long, pravidly pro pojmenování proměnných, základními matematickými operátory a aritmetickými výrazy a obsazováním typů.

Skutečná síla vámi vytvořených programů spočívá v jejich manipulaci s daty. Abyste mohli tuto sílu skutečně využít, musíte lépe porozumět různým datovým typům, které můžete používat, a také tomu, jak vytvářet a pojmenovávat proměnné. Jazyk C disponuje bohatou škálou matematických operátorů, které můžete používat k manipulaci s daty. V této kapitole se budete zabývat:

  • Datové typy int, float, double, char a _Bool
  • Modifikace datových typů pomocí short, long, a long long
  • Pravidla pro pojmenování proměnných
  • Základní matematické operátory a aritmetické výrazy
  • Odlévání typů

Poznání datových typů a konstant

S základním datovým typem int jazyka C jste se již seznámili. Jak si jistě vzpomínáte, proměnná deklarovaná jako typ int může být použita pouze pro integrální hodnoty – to znamená hodnoty, které neobsahují desetinná místa.

Programovací jazyk C poskytuje další čtyři základní datové typy: float, double, char a _Bool. Proměnnou deklarovanou jako typ float lze použít pro ukládání čísel s pohyblivou řádovou čárkou (hodnot obsahujících desetinná místa). Typ double je stejný jako typ float, jen má zhruba dvojnásobnou přesnost. Datový typ char lze použít k uložení jednoho znaku, například písmene „a“, znaku číslice „6“ nebo středníku („;“) (více o tom později). A konečně datový typ _Bool lze použít k uložení pouze hodnot 0 nebo 1. Proměnné tohoto typu se používají pro označení situace zapnuto/vypnuto, ano/ne nebo pravda/nepravda. Tyto volby typu jedno-nebo-jiné jsou také známé jako binární volby.

V jazyce C je jakékoliv číslo, jeden znak nebo řetězec znaků znám jako konstanta. Například číslo 58 představuje konstantní celočíselnou hodnotu. Řetězec znaků „Programování v C je zábava.\n“ je příkladem konstantního řetězce znaků. Výrazy složené výhradně z konstantních hodnot se nazývají konstantní výrazy. Výraz

128 + 7 - 17

je tedy konstantní výraz, protože každý z členů výrazu je konstantní hodnota. Pokud by však i bylo deklarováno jako celočíselná proměnná, výraz

128 + 7 – i

by nepředstavoval konstantní výraz, protože jeho hodnota by se měnila v závislosti na hodnotě i. Pokud je i 10, výraz je roven 125, ale pokud je i 200, výraz je roven -65.

Celočíselný typ int

V jazyce C se celočíselná konstanta skládá z posloupnosti jedné nebo více číslic. Znaménko minus před posloupností znamená, že hodnota je záporná. Hodnoty 158, -10 a 0 jsou všechny platnými příklady celočíselných konstant. Mezi číslicemi nejsou povoleny žádné vložené mezery a hodnoty větší než 999 nelze vyjádřit pomocí čárek. (Hodnota 12 000 tedy není platnou celočíselnou konstantou a musí být zapsána jako 12000.)

Dva speciální formáty v jazyce C umožňují vyjádřit celočíselné konstanty v jiném než desetinném základu (základ 10). Pokud je první číslicí celočíselné hodnoty 0, je celé číslo bráno jako vyjádřené v osmičkové notaci – tedy v základu 8. V takovém případě musí být zbývající číslice hodnoty platnými číslicemi základu 8, a proto musí mít hodnotu 0-7. Pro vyjádření hodnoty 50 v základu 8 v jazyce C, která je ekvivalentní hodnotě 40 v desítkové soustavě, se tedy používá zápis 050. Podobně osmičková konstanta 0177 představuje v desítkové soustavě hodnotu 127 (1 × 64 + 7 × 8 + 7). Celočíselnou hodnotu lze na terminálu zobrazit v osmičkové notaci pomocí formátovacích znaků %o ve formátovacím řetězci příkazu printf(). V takovém případě se hodnota zobrazí v osmičkové soustavě bez úvodní nuly. Formátovací znak %#o způsobí, že se před osmičkovou hodnotou zobrazí úvodní nula.

Předchází-li celočíselné konstantě nula a písmeno x (malé nebo velké), je hodnota považována za vyjádřenou v hexadecimálním zápisu (základ 16). Bezprostředně za písmenem x následují číslice hexadecimální hodnoty, které mohou být složeny z číslic 0-9 a písmen a-f (nebo A-F). Písmena představují hodnoty 10-15, resp. Pro přiřazení hexadecimální hodnoty FFEF0D do celočíselné proměnné s názvem rgbColor lze tedy použít příkaz

rgbColor = 0xFFEF0D;

. Formátovací znaky %x zobrazují hodnotu v hexadecimálním formátu bez počátečního znaku 0x a pro hexadecimální číslice používají malá písmena a-f. Chcete-li zobrazit hodnotu s počátečním 0x, použijete formátovací znaky %#x, jako v následujícím případě:

printf ("Color is %#x\n", rgbColor);

K zobrazení počátečního x a následujících šestnáctkových číslic pomocí velkých písmen lze použít velké písmeno x, jako je %X nebo %#X.

Velikosti úložiště a rozsahy

Každá hodnota, ať už jde o znak, celé číslo nebo číslo s pohyblivou řádovou čárkou, má přiřazen rozsah hodnot. Tento rozsah souvisí s velikostí úložiště, které je přiděleno pro uložení určitého typu dat. Obecně platí, že toto množství není v jazyce definováno. Obvykle závisí na provozovaném počítači, a proto se nazývá implementačně nebo strojově závislé. Například celé číslo může na vašem počítači zabírat 32 bitů, nebo třeba může být uloženo v 64 bitech. Nikdy byste neměli psát programy, které předpokládají jakoukoli velikost datových typů. Máte však zaručeno, že pro každý základní datový typ bude vyhrazeno minimální množství paměti. Například je zaručeno, že hodnota celého čísla bude uložena minimálně ve 32 bitech paměti, což je velikost „slova“ na mnoha počítačích.

Proměnná typu float

Proměnnou deklarovanou jako typ float lze použít pro ukládání hodnot obsahujících desetinná místa. Konstanta s pohyblivou řádovou čárkou se vyznačuje přítomností desetinné čárky. Můžete vynechat číslice před desetinnou čárkou nebo číslice za desetinnou čárkou, ale samozřejmě nemůžete vynechat obě. Hodnoty 3., 125,8 a -.0001 jsou všechny platnými příklady konstant s pohyblivou desetinnou čárkou. Pro zobrazení hodnoty s pohyblivou desetinnou čárkou na terminálu se používají konverzní znaky printf %f.

Konstanty s pohyblivou desetinnou čárkou lze také vyjádřit ve vědecké notaci. Hodnota 1,7e4 je hodnota s pohyblivou řádovou čárkou vyjádřená v této notaci a představuje hodnotu 1,7 × 104. Hodnota před písmenem e se nazývá mantisa, zatímco hodnota, která následuje, se nazývá exponent. Tento exponent, kterému může předcházet nepovinné znaménko plus nebo minus, představuje mocninu 10, kterou má být mantisa vynásobena. V konstantě 2,25e-3 je tedy 2,25 hodnotou mantisy a -3 hodnotou exponentu. Tato konstanta představuje hodnotu 2,25 × 10-3 neboli 0,00225. Mimochodem, písmeno e, které odděluje mantisu od exponentu, lze zapsat jak malými, tak velkými písmeny.

Chcete-li hodnotu zobrazit ve vědecké notaci, měli byste ve formátovacím řetězci printf() zadat formátovací znaky %e. Formátovací znaky %g lze použít k tomu, aby se funkce printf() rozhodla, zda hodnotu s pohyblivou řádovou čárkou zobrazí v normálním zápisu s pohyblivou řádovou čárkou, nebo ve vědeckém zápisu. Toto rozhodnutí je založeno na hodnotě exponentu: Pokud je menší než -4 nebo větší než 5, použije se formát %e (vědecká notace); v opačném případě se použije formát %f.

Pro zobrazení čísel s pohyblivou řádovou čárkou použijte znaky formátu %g – vytváří nejestetičtější výstup.

Šestnáctková plovoucí konstanta se skládá z úvodního znaku 0x nebo 0X, za kterým následuje jedna nebo více desetinných nebo šestnáctinných číslic, za nimiž následuje znak p nebo P a za nimi volitelně podepsaný binární exponent. Například 0x0.3p10 představuje hodnotu 3/16 × 210 = 0,5.

Typ s rozšířenou přesností double

Typ double je velmi podobný typu float, ale používá se vždy, když rozsah poskytovaný proměnnou float není dostatečný. Proměnné deklarované jako typ double mohou uchovávat zhruba dvakrát více významných číslic než proměnná typu float. Většina počítačů reprezentuje hodnoty typu double pomocí 64 bitů.

Pokud není řečeno jinak, překladač jazyka C bere všechny konstanty typu floating-point jako hodnoty typu double. Chcete-li explicitně vyjádřit konstantu typu float, připojte na konec čísla znak f nebo F takto:

12.5f

Pro zobrazení dvojnásobné hodnoty lze použít formátovací znaky %f, %e nebo %g, což jsou stejné formátovací znaky, které se používají pro zobrazení hodnoty typu float.

Proměnná typu char

Proměnnou typu char lze použít pro uložení jednoho znaku.1 Znaková konstanta se vytvoří uzavřením znaku do dvojice jednoduchých uvozovek. Takže „a“, „;“ a „0“ jsou všechny platné příklady znakových konstant. První konstanta představuje písmeno a, druhá je středník a třetí je znak nula – což není totéž jako číslo nula. Nezaměňujte znakovou konstantu, což je jeden znak uzavřený v jednoduchých uvozovkách, se znakovým řetězcem, což je libovolný počet znaků uzavřených ve dvojitých uvozovkách.

Znaková konstanta ‚\n‘ – znak nového řádku – je platnou znakovou konstantou, i když se zdá, že je v rozporu s dříve citovaným pravidlem. Je to proto, že znak zpětného lomítka je v systému C speciálním znakem a ve skutečnosti se jako znak nepočítá. Jinými slovy, překladač jazyka C považuje znak ‚\n‘ za jediný znak, i když je ve skutečnosti tvořen dvěma znaky. Existují i další speciální znaky, které jsou iniciovány znakem zpětného lomítka. Úplný seznam najdete v příloze A, „Shrnutí jazyka C“.

Formátovací znaky %c lze použít ve volání funkce printf() pro zobrazení hodnoty proměnné char na terminálu.

Boleovský datový typ _Bool

Proměnná _Bool je v jazyce definována jako dostatečně velká pro uložení pouze hodnot 0 a 1. Přesné množství paměti, které se používá, není specifikováno. Proměnné _Bool se používají v programech, které potřebují indikovat logickou podmínku. Proměnná tohoto typu může například indikovat, zda byla ze souboru přečtena všechna data.

Podle konvence se 0 používá pro označení nepravdivé hodnoty a 1 označuje pravdivou hodnotu. Při přiřazování hodnoty proměnné _Bool je hodnota 0 uložena uvnitř proměnné jako 0, zatímco jakákoli nenulová hodnota je uložena jako 1.

Pro usnadnění práce s proměnnými _Bool ve vašem programu definuje standardní hlavičkový soubor <stdbool.h> hodnoty bool, true a false. Příklad je uveden v programu 5.10A v kapitole 5, „Rozhodování“.

V programu 3.1 jsou použity základní datové typy jazyka C.

Program 3.1 Použití základních datových typů

Program 3.1 Výstup

integerVar = 100floatingVar = 331.790009doubleVar = 8.440000e+11doubleVar = 8.44e+11charVar = WboolVar = 0;

První příkaz programu 3.1 se skládá ze dvou datových typů.1 deklaruje proměnnou integerVar jako celočíselnou proměnnou a také jí přiřazuje počáteční hodnotu 100, jako by místo toho byly použity následující dva příkazy:

int integerVar;integerVar = 100;

V druhém řádku výstupu programu si všimněte, že hodnota 331,79, která je přiřazena proměnné floatingVar, je ve skutečnosti zobrazena jako 331,790009. Ve skutečnosti je skutečná zobrazená hodnota závislá na konkrétním počítačovém systému, který používáte. Důvodem této nepřesnosti je zvláštní způsob, jakým jsou čísla uvnitř počítače interně reprezentována. Se stejným typem nepřesnosti jste se pravděpodobně setkali při práci s čísly na kapesní kalkulačce. Pokud na kalkulačce vydělíte 1 třemi, dostanete výsledek .33333333, na jehož konci je možná přidáno několik dalších trojek. Řetězec trojek je přibližný údaj kalkulačky k jedné třetině. Teoreticky by jich mělo být nekonečně mnoho. Kalkulačka však dokáže pojmout pouze tolik číslic, což je její přirozená nepřesnost. Stejný typ nepřesnosti platí i zde:

Při zobrazování hodnot proměnných typu float nebo double máte na výběr ze tří různých formátů. Znaky %f slouží k zobrazení hodnot standardním způsobem. Pokud není řečeno jinak, funkce printf() vždy zobrazí hodnotu float nebo double zaokrouhlenou na šest desetinných míst. Později v této kapitole uvidíte, jak vybrat počet desetinných míst, která se zobrazí.

Znaky %e se používají k zobrazení hodnoty proměnné float nebo double ve vědecké notaci. Systém opět automaticky zobrazí šest desetinných míst.

Pomocí znaků %g si funkce printf() vybírá mezi %f a %e a také automaticky odstraní ze zobrazení všechny koncové nuly. Pokud za desetinnou čárkou nenásleduje žádná číslice, nezobrazí ani tu.

V předposledním příkazu printf() se pomocí znaků %c zobrazí jediný znak ‚W‘, který jste přiřadili proměnné charVar při její deklaraci. Nezapomeňte, že zatímco znakový řetězec (například první argument příkazu printf()) je uzavřen do dvojice dvojitých uvozovek, znaková konstanta musí být vždy uzavřena do dvojice jednoduchých uvozovek.

Poslední příkaz printf() ukazuje, že hodnota proměnné _Bool může být zobrazena pomocí znaků formátu celého čísla %i.

Specifikátory typu: long, long long, short, unsigned a signed

Pokud je specifikátor long umístěn přímo před deklaraci int, má deklarovaná celočíselná proměnná na některých počítačových systémech rozšířený rozsah. Příkladem deklarace long int může být

long int factorial;

Tímto deklarujeme proměnnou factorial jako celočíselnou proměnnou long. Stejně jako u proměnných typu float a doubles závisí konkrétní přesnost dlouhé proměnné na konkrétním počítačovém systému. V mnoha systémech mají proměnné int a long int stejný rozsah a obě mohou být použity k uložení celočíselných hodnot až do šířky 32 bitů (231 – 1, neboli 2 147 483 647).

Konstantní hodnota typu long int se vytvoří volitelným připojením písmene L (velké nebo malé písmeno) na konec celočíselné konstanty. Mezi číslem a písmenem L nejsou povoleny žádné mezery. Deklarace

long int numberOfPoints = 131071100L;

tak deklaruje proměnnou numberOfPoints jako proměnnou typu long int s počáteční hodnotou 131 071 100.

Pro zobrazení hodnoty long int pomocí funkce printf() se před znaky formátu celého čísla i, o a x použije písmeno l jako modifikátor. To znamená, že pomocí formátovacích znaků %li lze zobrazit hodnotu long int v desítkovém formátu, pomocí znaků %lo lze zobrazit hodnotu v osmičkovém formátu a pomocí znaků %lx lze zobrazit hodnotu v šestnáctkovém formátu.

Existuje také datový typ long long integer, takže

long long int maxAllowedStorage;

prohlásí uvedenou proměnnou s uvedenou rozšířenou přesností, která má zaručenou šířku alespoň 64 bitů. Místo jednoho písmene l se pro zobrazení dlouhých dlouhých celých čísel v řetězci printf používají dvě l, jako například „%lli“.

Specifikátor long je povolen i před deklarací dvojčete, a to takto:

long double US_deficit_2004;

Dlouhá dvojčíselná konstanta se zapisuje jako plovoucí konstanta s písmenem l nebo L bezprostředně za ní, například

1.234e+7L

Pro zobrazení dlouhého dvojčete se používá modifikátor L. Takže %Lf zobrazí hodnotu long double v zápisu s pohyblivou řádovou čárkou, %Le zobrazí stejnou hodnotu ve vědeckém zápisu a %Lg říká funkci printf(), aby si vybrala mezi %Lf a %Le.

Specifikátor short, je-li umístěn před deklaraci int, říká překladači jazyka C, že konkrétní deklarovaná proměnná slouží k ukládání poměrně malých celočíselných hodnot. Motivací pro použití proměnných short je především úspora místa v paměti, což může být problém v situacích, kdy program potřebuje hodně paměti a množství dostupné paměti je omezené.

Na některých počítačích zabírá proměnná short int polovinu místa v paměti než běžná proměnná int. V každém případě máte zaručeno, že velikost prostoru přiděleného pro proměnnou short int nebude menší než 16 bitů.

Neexistuje žádný způsob, jak explicitně zapsat konstantu typu short int v jazyce C. Chcete-li zobrazit proměnnou short int, umístěte písmeno h před některý z běžných znaků pro převod celých čísel: %hi, %ho nebo %hx. Alternativně můžete pro zobrazení krátkých intů použít také některý ze znaků pro převod celých čísel, a to díky způsobu, jakým mohou být převedeny na celá čísla, když jsou předávány jako argumenty rutině printf().

Poslední specifikátor, který lze umístit před proměnnou int, se používá v případě, že celočíselná proměnná bude sloužit k ukládání pouze kladných čísel. Deklarace

unsigned int counter;

deklaruje překladači, že čítačová proměnná bude sloužit k ukládání pouze kladných hodnot. Omezením použití celočíselné proměnné na výhradní ukládání kladných celých čísel se rozšíří přesnost celočíselné proměnné.

Konstantu unsigned int vytvoříte tak, že za konstantu umístíte písmeno u (nebo U), a to takto:

0x00ffU

Při zápisu celočíselné konstanty můžete kombinovat písmena u (nebo U) a l (nebo L), takže

20000UL

říká překladači, aby s konstantou 20000 zacházel jako s konstantou unsigned long.

Celočíselnou konstantu, za kterou nenásleduje žádné z písmen u, U, l nebo L a která je příliš velká na to, aby se vešla do normální velikosti int, zpracuje překladač jako unsigned int. Pokud je příliš malá na to, aby se vešla do nepodepsaného int, překladač s ní zachází jako s long int. Pokud se stále nevejde do long int, překladač z něj udělá unsigned long int. Pokud se tam nevejde, překladač s ním zachází jako s long long int, pokud se tam vejde, a jako s unsigned long long int v opačném případě.

Při deklaraci proměnných typu long long int, long int, short int nebo unsigned int můžete klíčové slovo int vynechat. Proměnná čítač bez znaménka by tedy mohla být ekvivalentně deklarována takto:

unsigned counter;

Můžete také deklarovat proměnné char jako proměnné bez znaménka.

Kvalifikátor signed lze použít k explicitnímu sdělení překladači, že určitá proměnná je veličina se znaménkem. Jeho použití je především před deklarací char a další diskuse o něm je odložena do kapitoly 13, „Více o datových typech.“

Neznepokojujte se, pokud vám diskuse o těchto specifikátorech připadá na tomto místě poněkud esoterická. V dalších částech této knihy je mnoho z těchto různých typů ilustrováno na skutečných příkladech programů. Podrobněji se datovým typům a konverzím věnuje kapitola 13.

Tabulka 3.1 shrnuje základní datové typy a kvalifikátory.

Tabulka 3.1 Základní datové typy

.