Image
9.6.2016 0 Comments

C++ / Typy jazyka C++ / 4. časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Toto pokračovanie seriálu začnem trochu retrospektívne, niekoľkými záležitosťami okolo druhej časti seriálu – výrobná lehota PC REVUE mi, žiaľ, nedovoľuje reagovať na predchádzajúce časti skôr ako o dva mesiace. Takže v prvom rade sa ospravedlňujem za menšie chyby v ukážkovom programe. Niežeby sa nedal preložiť, ale, ako ste hádam aj sami zistili, po spustení vypísal všetky texty do jedného riadka. Po prečítaní predošlej časti by ste mali byť schopní urobiť patričnú úpravu sami, takže len pre istotu dodávam, že na koniec každého vypisovaného textu patrí (tesne pred koncové úvodzovky) escape sekvencia \n, ktorá spôsobí chýbajúci prechod na nový riadok. Ďalšou „chybou“ je preklep – vo funkcii main() má byť vo vypisovanom reťazci namiesto form slovo from (a na konci reťazca chýba bodka – ale to už len pre vyslovených punktičkárov, ako som napríklad ja…).

Druhá vec, ktorá ma trápi o niečo viac, je nadpis článku druhého dielu. Verejne prehlasujem, že taký ťažký zločin, ako je mäkké i vo výraze „Tipy súborov,“ som nespáchal ja, ale (asi) niekto z DTP. Pozdravujem týmto všetky svoje bývalé učiteľky slovenského jazyka a oznamujem im, že môžu pokojne spávať.

Opakovanie

V predošlej časti sme prebrali lexikálne jednotky jazyka C++. Verím, že nešlo o práve najzrozumiteľnejšie čítanie, ale máme to aspoň za sebou. Povedali sme si, že program v C++ je postupnosťou lexikálnych jednotiek, oddelených bielymi znakmi. Dve lexikálne jednotky musia byť oddelené jedným alebo viacerými bielymi znakmi vtedy, ak by ich nebolo možné inak rozlíšiť. Uvediem príklad: majme postupnosť znakov a--b. O tejto postupnosti nedokážeme rozhodnúť, či ide o odčítanie zápornej premennej b od premennej a alebo o operáciu dekrementácie premennej a (-- je operátor dekrementácie – zníženia hodnoty o 1) nasledovanú zápisom premennej b (hoci tento výraz nemá zmysel). Preto je potrebné do postupnosti vložiť na vhodné miesto nejaký biely znak, najčastejšie medzeru – v prvom prípade dostaneme výraz a - - b, v druhom a-- b. Toľko na ilustráciu.

Je možné, že ešte stále nemáte v tejto oblasti celkom jasno, preto si rozložíme teraz náš prvý program na postupnosť lexikálnych jednotiek. Najprv to však skúste sami a až potom si prečítajte správne riešenie. Tu je program:

 

#include <stdio.h>

 

int main()

{

    printf("Hello, world!\n");

    return 0;

}

 

a tu je jeho dekompozícia:

1.   #include <stdio.h> je direktíva preprocesora, nie je to lexikálna jednotka (nahradí sa obsahom súboru STDIO.H, ktorý je sám osebe postupnosťou lexikálnych jednotiek). O direktívach preprocesora si povieme v niektorej z budúcich častí seriálu.

2.   Nasledujú dva prechody na nový riadok. Prechod na nový riadok je v zdrojovom súbore uložený ako kombinácia dvoch ASCII znakov – CR (ASCII kód 13) a LF (ASCII kód 10). Znak vyjadrený escape sekvenciou \n (čo je znak LF) sa pri výpise na obrazovku automaticky prevedie na dvojicu CR/LF. Tento prevod je do istej miery daný službami operačného systému a bližšie si o ňom povieme, keď budeme preberať štandardnú knižnicu jazyka C.

3.   int je kľúčové slovo jazyka C++ a v našom programe určuje typ návratovej hodnoty funkcie main(). Za ním nasleduje jedna medzera – biely znak. main je identifikátor, ktorý predstavuje názov funkcie, dvojica znakov () by sa dala považovať za operátor, respektíve v tomto kontexte aj za „iný oddeľovač“.

4.   Prechod na nový riadok, na tomto riadku je jediný znak – oddeľovač {, začínajúci definíciu tela funkcie main().

5.   Opäť prechod na nový riadok a po ňom štyri medzery.

6.   printf je identifikátor predstavujúci meno knižničnej funkcie. Po ňom nasleduje otváracia zátvorka, ktorá je súčasťou operátora (). Za zátvorkou je reťazcová konštanta – "Hello, world!\n", ktorá je argumentom funkcie printf(). Riadok je ukončený zatváracou zátvorkou a oddeľovačom ;, slúžiacim na oddeľovanie viacerých príkazov nasledujúcich za sebou.

7.   Ďalší prechod na nový riadok a po ňom zase štyri medzery.

8.   return je kľúčové slovo jazyka C++, po ňom nasleduje medzera a celočíselná konštanta 0, ktorej hodnotu program vráti operačnému systému ako návratový kód. Na konci riadka je opäť oddeľovač ;.

9.   Posledný prechod na nový riadok a oddeľovač }, ktorý definíciu funkcie main() ukončuje.

Ak náhodou máte pocit, že to, čo tu teraz vysvetľujem, je zbytočné, nepochopiteľné a nepraktické, ubezpečujem vás, že všetko, čo ste sa o lexikálnych jednotkách dozvedeli, časom zužitkujete. Už viete, z akých prvkov sa program v C++ skladá, a pri pohľade na cudzí program by ste do určitej miery mali vedieť, čo je čo. Ide o podobnú situáciu, ako keď sa učíte cudzí jazyk – ak zhruba ovládate stavbu vety, viete, čo je podmet, čo prísudok a podobne, ľahšie sa zorientujete v nejakej vete, aj keď vaša slovná zásoba za veľa nestojí.

Typy

Na začiatok niečo o tom, čo si predstavujeme pod pojmom typy. Keď píšeme nejaký program, väčšinou od neho očakávame, aby robil niečo užitočné. To vedie prakticky vždy k spracúvaniu nejakých údajov (ostatne, načo tie počítače vlastne máme, že?). Tieto údaje sú však rôznorodého charakteru, môžeme povedať, že majú rôzne typy. Program, ktorý s údajmi pracuje, musí vedieť, s akým typom údajov pracuje. Pod pojmom typ v jazyku C++ teda budeme rozumieť charakter údajov, ktoré sa v programe používajú. Azda bude lepšie namiesto o údajoch hovoriť o objektoch jazyka C++, hoci nejde o objekty známe z teórie objektovoorientovaného programovania, ale skôr o objekty fyzicky existujúce počas behu programu – v podstate sú to premenné a funkcie.

Typy jazyka C++ môžeme rozdeliť na dve skupiny – základné a odvodené typy.

Základné typy

Prvým z množiny základných typov je char. Ako jeho názov napovedá, tento typ sa používa na reprezentáciu znakov znakovej sady daného počítača a jeho veľkosť je taká, aby bolo možné pomocou neho reprezentovať ľubovoľný znak tejto sady. Prakticky v každej implementácii C++ na PC je to 8 bitov – teda jeden bajt. Znak je v premennej typu char reprezentovaný svojou hodnotou v kóde ASCII, teda napríklad znak 'A' je uložený ako hodnota 65, a keďže kód ASCII obsahuje 256 znakov (mám na mysli 8-bitový kód ASCII), potrebujeme na ich vyjadrenie práve 8 bitov. Premennej typu char môžeme priradiť priamo číselnú konštantu v danom rozmedzí, dôsledok bude rovnaký ako po priradení znakovej konštanty. Nasledujúce dva zápisy sú teda ekvivalentné (predpokladáme, že c je premenná typu char):

 

c = 'A';

c = 65;

 

Čo je zaujímavé, premennú typu char vôbec nemusíme používať tak, akoby obsahovala znak, ale jednoducho ako celočíselnú premennú s rozsahom 256 hodnôt.

Typ char môže byť explicitne deklarovaný ako signed char alebo unsigned char (mimochodom, signed znamená „so znamienkom“ a unsigned „bez znamienka“). Tieto dve modifikácie sa líšia rozsahom hodnôt, ktoré im možno priradiť (pozri tab. 1). Treba si však uvedomiť, že veľkosť oboch typov je rovnaká, t. j. 8 bitov, líši sa iba reprezentácia uložených údajov pri ich použití. Typ unsigned char ukladá znaky ako 8-bitové čísla bez znamienka (0 ÷ 255), typ signed char ich ukladá ako 8-bitové čísla so znamienkom v doplnkovom kóde (–128 ÷ 127). Znaky z dolnej polovice kódu ASCII (0 ÷ 127) sú teda prezentované pri oboch typoch rovnako, prezentácia znakov z hornej polovice sa líši – pri type signed char ide o rozsah –128 ÷ –1, pri type unsigned char o rozsah 128 ÷255.

Pre istotu uvediem ešte príklad: znak 'ô' s kódom ASCII 147 (v kódovej stránke 852, t. j. Latin-2) je v prípade uloženia do premennej typu unsigned char prezentovaný (a prípadne použitý) ako číslo 147, zatiaľ čo v prípade uloženia do premennej typu signed char dostaneme pri použití číslo –109 ( =147 – 256). V pamäti je však v oboch prípadoch uložený ako binárne číslo 10010011.

Typ char je vždy implementovaný ako jeden z typov signed char alebo unsigned char, ale pozor, z hľadiska prekladača sú všetky tri typy považované za navzájom rôzne!

Ďalším typom, ktorý v C++ existuje, je typ int. Jeho názov je odvodený z anglického slova integer, čo znamená celé číslo, logicky teda môžeme predpokladať, že tento typ sa používa na uchovanie celočíselných údajov. Jeho veľkosť je obyčajne taká, aby s ňou procesor, pre ktorý je daný program určený, pracoval čo najefektívnejšie. Napríklad v programoch určených pre reálny alebo 16-bitový chránený režim procesora x86 (programy pre MS-DOS, MS Windows 3.x) je veľkosť typu int 16 bitov, v programoch určených pre 32-bitový chránený režim (MS Windows 95, NT) je jeho veľkosť 32 bitov. Povolený rozsah hodnôt pre oba prípady je v tab. 1. Všimnite si, že typ int sa používa na uchovávanie hodnôt so znamienkom.

V prípade, že chceme explicitne použiť menší či väčší rozsah, máme k dispozícii dva modifikované typy – short int a long int. Ich veľkosť nie je nijako garantovaná, jediné, na čo sa môžeme spoliehať, je, že veľkosť typu long int nebude menšia ako veľkosť typu int a tá zase nebude menšia ako veľkosť typu short int. Vo väčšine implementácií jazyka C++ na PC má typ short int veľkosť 16 bitov a typ long int 32 bitov. Povolené rozsahy ich hodnôt sú opäť v tab. 1.

Takto definované typy sa všetky používajú na reprezentáciu čísel so znamienkom. Čo však v prípade, že potrebujeme uchovávať čísla bez znamienka? Na tieto účely máme v C++ k dispozícii k spomenutým trom celočíselným typom ich neznamienkové modifikácie – zoradené podľa veľkosti sú to unsigned short int, unsigned int a unsigned long int. Od svojich znamienkových ekvivalentov sa líšia rozsahom povolených hodnôt (pozri tab. 1), inak ich veľkosti a spôsob uloženia v pamäti sú zhodné, podobne ako pri type char.

 

Typ

Veľosť

Rozsah hodnôt

Rozsah hodnôt inak

char

8 bitov

podľa implementácie

podľa implementácie

signed char

8 bitov

–128 ÷ 127

–27 ÷ 27 – 1

unsigned char

8 bitov

0 ÷ 255

0 ÷ 28 – 1

short int

16 bitov

–32768 ÷ 32767

–215 ÷ 215 – 1

int (16bit)

16 bitov

–32768 ÷ 32767

–215 ÷ 215 – 1

int (32bit)

32 bitov

–2147483648 ÷ 2147483647

–231 ÷ 231 – 1

long int

32 bitov

–2147483648 ÷ 2147483647

–231 ÷ 231 – 1

unsigned short int

16 bitov

0 ÷ 65535

0 ÷ 216 – 1

unsigned int (16bit)

16 bitov

0 ÷ 65535

0 ÷ 216 – 1

unsigned int (32bit)

32 bitov

0 ÷ 4294967295

0 ÷ 232 – 1

unsigned long int

32 bitov

0 ÷ 4294967295

0 ÷ 232 – 1

float

32 bitov

± 3.4 × 10–38 ÷ ± 3.4 × 1038

± 2–126 ÷ ± 2128

double

64 bitov

± 2.2 × 10–308 ÷ ± 1.8 × 10308

± 2–1022 ÷ ± 21024

long double

80 bitov

± 3.4 × 10–4932 ÷ ± 1.2 × 104932

± 2–16382 ÷ ± 216384

         

 

Tretím typom, alebo skôr množinou typov, sú typy s pohyblivou rádovou čiarkou. Sú tri: float, double a long double. Líšia sa svojou veľkosťou a presnosťou vyjadrovania reálnych čísel. Podobne ako pri celočíselných typoch nemáme túto presnosť nijako zaručenú, môžeme si byť iba istí, že presnosť typu long double nebude menšia ako presnosť typu double a tá zase nebude menšia ako presnosť typu float.

Jednotlivé implementácie C++ môžu mať rôzne veľkosti (na otázku, ako to je vo vašom prekladači, nájdete určite odpoveď v manuáli alebo elektronickej nápovedi), ako príklad sú v tab. 1 uvedené rozsahy týchto typov v Borland C++ 3.1. V tomto prekladači je typ float reprezentovaný 32-bitovým, typ double 64-bitovým a typ long double 80-bitovým číslom podľa štandardu IEEE 754.

Posledným zo základných typov (vlastne skoro posledným, ešte existuje tzv. vymenovaný typ, o ktorom si povieme neskôr) je typ void. Void znamená po anglicky prázdny a tento typ sa používa v prípade, že nepracujeme so žiadnym konkrétnym údajom. V programe nemôže existovať premenná typu void, lebo by vlastne nemala zmysel. Jednou z možností použitia je vyjadrenie, že určitá funkcia nemá argumenty alebo nevracia nijakú hodnotu – ak si spomeniete na program z druhej časti seriálu, naše funkcie boli definované s návratovým typom void – nevracali tomu, kto ich zavolal, nijaký údaj. Ďalej sa typ void používa pri práci s ukazovateľmi „niekam do pamäte“, ale o ukazovateľoch si budeme hovoriť až nabudúce.

Typy konštánt

V predošlej časti sme sa zaoberali rôznymi konštantami, ale nepovedali sme si nič o tom, aké sú ich typy. Dnes už máme dostatočné znalosti, preto si tento výklad doplníme.

Znakové konštanty (s výnimkou „širokoznakových“) sú typu char.

Typ celočíselnej konštanty závisí od jej formy, hodnoty a prípadnej prípony. Najprv predpokladajme, že za konštantou nenasleduje nijaká prípona. Ak ide o desiatkovú konštantu, jej typ je prvým z nasledujúcich, do ktorého sa „zmestí“: int, long int, unsigned long int. Ak ide o osmičkovú alebo o šestnástkovú konštantu, jej typ je podobne jedným z nasledujúcich: int, unsigned int, long int, unsigned long int.

Ak za celočíselnou konštantou nasleduje prípona u alebo U, je jej typ podľa hodnoty unsigned int alebo unsigned long int. Ak za konštantou nasleduje prípona l alebo L, jej typ je jedným z nasledujúcich: long int, unsigned long int. A konečne, ak za celočíselnou konštantou nasledujú znaky ul, lu, uL, Lu, Ul, lU, UL alebo LU (všetky sú teda rovnocenné), je jej typ unsigned long int.

Typ konštanty s pohyblivou rádovou čiarkou je implicitne double. Ak chceme konštantu typu float, musíme za ňu pripísať príponu f alebo F. Ak, naopak, chceme konštantu long double, pripíšeme príponu l alebo L.

Posledné štyri odseky boli asi ťažko stráviteľné, ale čo sa dá robiť, presnosť je presnosť. Napravíme to aspoň zopár príkladmi – pozri tab. 2. Všimnite si druhý riadok, konštanta 45779 je typu long int, hoci rozsahovo by sa zmestila do typu unsigned int!

 

Konštanta

Typ

5263

int

45779

long int (!)

3000000000

unsigned long int

0x3A7B

int

0xA3F9

unsigned int

0x4C001E77

long int

0xFFFFFFFF

unsigned long int

92U

unsigned int

512000U

unsigned long int

1998L

long int

3201376444L

unsigned long int

362UL

unsigned long int

8.854E–12

double

3.14159F

float

0.766L

long double

 

Ukážkový program

Zatiaľ sme toho veľa nenaprogramovali. Ospravedlňujem sa, ale je to naozaj vo vašom záujme – nechcem vám dať k dispozícii dlhý program, ktorému takmer vôbec nebudete rozumieť. Na druhej strane som si vedomý toho, že najlepšie sa dá problém pochopiť na príkladoch. V tejto časti si preto uvedieme program, ktorý dokopy nerobí nič užitočné: deklaruje niekoľko premenných rôznych typov, priradí im hodnoty nejakých konštánt a nakoniec všetky premenné vypíše na obrazovku. O deklarácii premenných sme si ešte nehovorili, takže len v skratke – ak chceme deklarovať premennú nejakého základného typu, napíšeme najprv názov jej typu, jeden alebo viac bielych znakov a potom identifikátor premennej, pomocou ktorého sa budeme na ňu pri práci odkazovať. Celý riadok ukončíme bodkočiarkou. Priradenie hodnoty realizujeme uvedením identifikátora premennej, ďalej nasleduje operátor priradenia (klasické =, nie pascalovské := !), za ktorý zapíšeme priraďovanú hodnotu (nemusí to byť len konštanta, môže to byť aj iná premenná). Na výpis použijeme funkciu printf(), ktorej možnosti sú podstatne rozsiahlejšie ako výpis reťazca znakov (ako sme videli v predchádzajúcich programoch). Presný opis prvého argumentu tejto funkcie, pomocou ktorého celý výpis riadime, odporúčam vzhľadom na rozsiahlosť stručne prezrieť v manuáli prekladača (ale to nie je podmienkou – v kapitolách o štandardnej knižnici jazyka C si povieme viac). A tu je už sľubovaný program:

 

#include <stdio.h>

 

int main()

{

    char c;

    unsigned char uc;

    int i;

    long int li;

    unsigned int ui;

    unsigned long int uli;

    float f;

    double d;

 

    c = 'A';

    uc = '\x93';   // = 'ô'

    i = -1234;

    li = -654321;

    ui = 56789;

    uli = 3000000000;

    f = 2.99E+8f;

    d = -1.7E-50;

 

    printf("c   = %c\n", c);

    printf("uc  = %c\n", uc);

    printf("i   = %i\n", i);

    printf("li  = %li\n", li);

    printf("ui  = %u\n", ui);

    printf("uli = %lu\n", uli);

    printf("f   = %g\n", f);

    printf("d   = %lg\n", d);

 

    return 0;

}

 

Všetky celočíselné konštanty použité v programe majú typ daný svojou hodnotou, je teda zbytočné špecifikovať ho explicitne príponou. Program je viac-menej koncipovaný pre 16-bitové prostredie (MS-DOS), ak ho budete prekladať 32-bitovým prekladačom (ako napr. konzolovú aplikáciu pre Win32), dvojice premenných i, li a ui, uli budú mať rovnaký rozsah hodnôt.

Nabudúce

Dnes sme sa oboznámili so základnými typmi, nabudúce si povieme niečo o odvodených typoch. Súčasne by som sa začal venoval trochu problematike deklarácií objektov jazyka C++, podľa toho, koľko miesta mi zostane. Máte pred sebou mesiac času, odporúčam vám vyskúšať si v uvedenom programe rôzne typy konštánt, priraďovanie obsahov premenných medzi sebou a ich vypisovanie. Vzor na výpis každého dôležitejšieho typu je v programe; pre tých, ktorí majú záujem, formátovací reťazec pre short int je %hi, pre unsigned short int je to %hu a konečne pre long double je ním %Lg.

Prajem vám pekný mesiac lásky a nezabudnite, že láska k opačnému pohlaviu je predsa len krajšia ako láska k počítaču.

C++

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Ako zbaviť fotky hmly

08.12.2016 11:59

Hmla alebo dym sú často veľmi kreatívne nástroje. No všetkého veľa škodí. Fotka potom stráca kontrast a v podstate na nej nič nevidieť. Hmlu môžete neraz následnými úpravami odstrániť alebo zredukovať ...

Ako na to

Užitočné SW nástroje

08.12.2016 11:53

AllDup v4.0.3 Určenie: program na vyhľadávanie a odstraňovanie duplicitných súborov Vlastnosti: duplicitné súbory sa vyhľadávajú len na zvolených diskových jednotkách alebo len v rámci vybraných ...

Ako na to

Fotografovanie s bleskom

08.12.2016 11:47

Ak máte moderný fotoaparát so vstavaným alebo externým bleskom, zdá sa vám téma článku triviálna. Jednoducho nastavíte vhodný režim, vyberiete najlepšiu kompozíciu záberu, exponujete a o zvyšok sa už ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá