Obsah
V této kapitole se seznámíme s operátory a jejich rozdělením. Zaměříme se zejména na operátory aritmetické. Ukážeme si jejich použití s celočíselnými i racionálními operandy a nezapomeneme ani na výrazy smíšené.
Potřebné znalosti | |
K zvládnutí obsahu této kapitoly je nutné mít znalosti z kapitoly 2 a 3 - tedy znát strukturu programu, orientovat se v identifikátorech, klíčových slovech, komentářích, odsazovačích, číslech, řetězcích a konstantách (celočíselných, racionálních a znakových). A chápat také základy problematiky ukazatelů. |
S pomocí operátorů vytváříme výrazy. Zapíšeme-li například v matematice a + b hovoříme výrazu. Ten má dva operandy a a b a jeden operátor +. |
S operandy v jazyce C to není jednoduché. Mohou být tvořeny konstantami, identifikátory objektů, řetězci a voláním funkcí. Operandy však můžeme vytvářet i pomocí kombinací zmíněných možností a dalších operátorů i závorek.
Adresu proměnné určí překladač jazyka C velmi snadno. Typ výrazu je určen typem operandů. Jsou-li operandy stejného typu, je výsledek téhož typu. Jinak je typu největšího z uvedených operandů.
Příklad: | |
j = 5; d = 'z'; f = f + 3.14 *i; |
Protože přiřazení je výraz je možné několikanásobné přiřazení.
Příklad: | |
int i,j,k; i = j = k = 2; |
Teorie zavedla pro pravou stranu přiřazení pojmenování hodnotový výraz, zatímco stranu levou pojmenovává adresový výraz. V anglické terminologii i v některých českých textech se používá zkrácené označení rvalue - r-hodnota, respektive lvalue - l-hodnota.
ISO norma jazyka C dále důrazně nedoporučuje používat výrazy, kde se vlevo i vpravo od operátoru přiřazení mění stejná hodnota.
Příklad: | |
i = i++ *2; /* takto NE */ |
Aritmetické výrazy konstruujeme z operandů a aritmetických operátorů.
Zkusme si ještě jeden příklad, kde argumenty aritmetických operací jsou celočíselné a levá strana je racionální.
V tomto příkladu jasně vidíme, že výpočet na pravé straně probíhá podle typů operandů pravé strany. Teprve je-li to potřeba je výsledek převeden na typ odpovídajíc straně levé.
Proto je výsledek tohoto příkladu: i=5 j=25 r=8.000000 x=75.000000
Logické hodnoty jsou dva, pravda a nepravda. Norma ISO C říká, že hodnota nepravda je představována nulou, zatímco pravda jedničkou. V případě hodnoty pravda se ovšem jedná pouze o doporučení. Neboť užívaným anachronismem je považovat jakoukoliv nenulovou hodnotu za pravdu.
Pravidla pro určení výsledku známe z Booleovy algebry.
Pro demonstrování funkcí AND, OR a NOT si napíšeme jednoduchý příklad.
Máme následující relační operátory:
Tyto operátory jsou definovány pro operandy všech základních datových typů. Ovšem například pro ukazatele mají smysl pouze operátory rovnosti a nerovnosti. Výsledkem relačních operací jsou logické hodnoty pravda a nepravda.
Již podle názvu můžeme usuzovat, že nám bitové operátory umožňují provádět operace nad jednotlivými bity. Bitové operace je však možné provádět pouze s celočíselnými hodnotami.
Máme následující typy bitových operátorů:
Při bitovém posunu vlevo (vpravo) << (>>), se jednotlivé bity posouvají vlevo (vpravo), tedy do pozice s (binárně) vyšším (nižším) řádem. Na nejpravější (nejlevější) posunem vytvořenou pozici je umístěna nula. Posuny ovšem probíhají aritmeticky. To znamená, že uvedené pravidlo neplatí pro posun vpravo hodnoty celočíselného typu se znaménkem. V takovém případě se nejvyšší bit (znaménkový), zachovává. Takto se při posunu doplňuje do bitového řetězce nový bit. Naopak před posunem nejlevější (nejpravější) bit je odeslán do říše zapomnění.
Bitový posun o jeden (binární) řád vpravo, respektive vlevo, má stejný význam, jako celočíselné dělení, respektive násobení, dvěma. Je-li bitový posun o více než jeden řád, jedná se o násobení (dělení) příslušnou mocninou dvou. Přirozeně to platí pouze pro bitový posun celočíselných typů unsigned.
Obecný formát pro operátory bitového posunu vlevo (vpravo):
hodnota << počet-bitů hodnota >> počet-bitů
Bitové and &, or |, a xor ^ provádí příslušnou binární operaci s každým párem odpovídajících si bitů. Výsledek je umístěn do pozice stejného binárního řádu výsledku. Výsledky operací nad jednotlivými bity jsou stejné, jako v Booleově algebře. Bitové not ~ je operátorem unárním, provádí negaci každého bitu v bitovém řetězci jediného operandu. Tomuto operátoru se často říká bitový doplněk.
Pozn: | |
XOR dává výsledek jedna jen v případě různosti hodnot operandů. |
Nyní si ukážeme jednoduchý příklad použití bitových posunů.
Příklad 4.4. | |
/****************************** * op_bit.c * 19.03.2002 ******************************/ #include <stdio.h> int main() { printf("1 << 1 = \t%d\t%#x\n", 1 << 1, 1 << 1); printf("1 << 7 = \t%d\t%#x\n", 1 << 7, 1 << 7); printf("-1 >> 1 = \t%d\t%#x\n", -1 >> 1, -1 >> 1); printf("512 >> 8 = \t%d\t%#x\n", 512 >> 8, 512 >> 8); printf("2 & 1 = \t%d\t%#x\n", 2 & 1, 2 & 1); printf("2 | 1 = \t%d\t%#x\n", 2 | 1, 2 | 1); printf("2 ^ 1 = \t%d\t%#x\n", 2 ^ 1, 2 ^ 1); return 0; } |
Výsledkem tohoto programu je následující výpis:
1 << 1 = 2 0x2 1 << 7 = 128 0x80 -1 >> 1 = -1 0xffffffff 512 >> 8 = 2 0x2 2 & 1 = 0 0 2 | 1 = 3 0x3 2 ^ 1 = 3 0x3
Operace XOR má jednu zajímavou vlastnost. Máme-li dvě hodnoty A a B, pak je-li na výsledek operace A XOR B uplatněna znovu operace XOR s operandem B dostáváme operand A. Tuto vlastnost si demonstrujeme na příkladu.
Adresový operátor & je unární. Jak již název adresový operátor napovídá, umožňuje získat adresu objektu, na nějž je aplikován. Adresu objektu můžeme použít v nejrůznějších situacích, obvykle je to v souvislosti s předáváním výsledků funkcí. Takto například můžeme přečíst hodnoty dvou proměnných jedinou funkcí pro formátovaný vstup.
Příklad: | |
int i; float f; scanf("%d %f",&i, &f); |
Jazyk C obsahuje ternární (trojitý) operátor ?. Ternární operátor potřebuje tři operandy. Operátor ? se používá pro náhradu příkazu typu:
if(podmínka) příkaz1; else příkaz2;
Obecný formát operátoru ? je:
Podmínka je výraz, který je vyhodnocen jako pravdivý nebo nepravdivý. Je-li pravdivý dosadí se do proměnné hodnota výrazu1. Je-li nepravdivý, dosadí se do proměnné hodnota výrazu2. Důvodem použití operátoru ? je to, že překladač jazyka C může v tomto případě vytvářet mnohem efektivnější kód než při použití příkazu if-else.
Ukažme si použití podmíněného operátoru na příkladu. Mějme program, který načte číslo a v případě že je větší nebo rovno nule jej převede na jedničku a v případě, že zadané číslo bylo záporné, na mínus jedničku.
Operátor čárka má zcela jedinečnou funkci. Říká překladači udělej tohle a tohle a tohle. To znamená, že se čárka používá pro zřetězení několika operací.
V následujícím cyklu se čárka používá v inicializační části pro inicializaci dvou řídících proměnných cyklu a v části pro inkrementaci i a j.
Pozn: | |
O cyklu for si více řekneme v následující kapitole. |
Příklad: | |
for(i=0, j=0; i+j<pocet; i++, j++) ....... |
Hodnotu seznamu výrazů oddělených čárkami určuje výraz, který stojí nejvíce vpravo. V následujícím příkladu se do proměnné hodnota přiřadí číslo 100.
Příklad: | |
hodnota = (pocet, 90, 50, 100); |
Závorky jsou zde potřebné, neboť operátor čárka má nižší prioritu než přiřazovací operátor.
Někdy potřebujeme dočasně změnit typ proměnné. Můžeme například chtít používat pro nějaký výpočet hodnotu v pohyblivé řádové čárce, ale někde pro ni chceme zase použít operátor celočíselného dělení. Jelikož však lze tento operátor použít pouze na celá čísla máme problém. Jedním z možných řešení je vytvořit celočíselnou proměnnou, která se bude používat pro celočíselné dělení a ve vhodné chvíli ji přiřadit hodnotu proměnné s pohyblivou řádovou čárkou. To je však poněkud neelegantní řešení. Jiným řešení je použít přetypování, které způsobí dočasnou změnu typu.
Přetypování má obecný tvar:
kde typ je jméno platného typu jazyka C.
Příklad: | |
float f; f = 100.2; printf("%d", (int) f); /* přetypování na celé číslo */ |
Následující přehled všech operátorů ukazuje jejich prioritu od nejvyšší po nejnižší.
Tabulka 4.5.
|