Procedurlne programovanie 9 prednka Gabriela Koskov Obsah prklady
Procedurálne programovanie: 9. prednáška Gabriela Kosková
Obsah • príklady k štruktúram a ukazovateľom (2) • oddelený preklad • bitové operácie a polia
Príklad: simulácia pokladní v obchode • N pokladní v obchode ZAKAZNIK *pokladne[N]; • Pri každej pokladni – rad zákazníkov typedef struct zakaznik { int cislo; struct zakaznik *dalsi; } ZAKAZNIK; • funkcie: – Výpis všetkých zákazníkov – Pridanie zákazníka – Vybavenie zákazníka (ten odíde)
Príklad: simulácia pokladní v obchode void vypis_vsetkych_zakaznikov(ZAKAZNIK *pokladne[N]); void pridaj_zakaznika(ZAKAZNIK *pokladne[N]); ZAKAZNIK *vyrob_zakaznika(int z); int najkratsi_rad(ZAKAZNIK *pokladne[N]); void vybaveny_zakaznik(int p, ZAKAZNIK *pokladne[N]); • Námety na zamyslenie void odchod_zakaznika(int cislo, ZAKAZNIK *pokladne[N]); int main(); • Uzatvorenie pokladne (potrebné zmeny aj v iných funkciách)
void vypis_vsetkych_zakaznikov(ZAKAZNIK *pokladne[N]) { int i; ZAKAZNIK *akt; for(i=0; i<N; i++) { akt = pokladne[i]; printf("Pokladna %d: ", i); while(akt != NULL) { printf("%d ", akt->cislo); akt = akt->dalsi; } printf("n"); } } ZAKAZNIK *vyrob_zakaznika(int z) { ZAKAZNIK *zak = (ZAKAZNIK *) malloc(sizeof(ZAKAZNIK)); zak->cislo = z; zak->dalsi = NULL; return zak; }
void pridaj_zakaznika(ZAKAZNIK *pokladne[N], int z) { int min = najkratsi_rad(pokladne); ZAKAZNIK *akt = pokladne[min]; if(akt == NULL) pokladne[min] = vyrob_zakaznika(z); else { akt = pokladne[min]; while(akt->dalsi != NULL) akt = akt->dalsi; akt->dalsi = vyrob_zakaznika(z); } }
int najkratsi_rad(ZAKAZNIK *pokladne[N]) { int min_dlzka, najkratsi, i, dlzka; ZAKAZNIK *akt; for(i=0; i<N; i++) { dlzka = 0; akt = pokladne[i]; while(akt != NULL) { dlzka++; akt = akt->dalsi; } if(i==0 || dlzka < min_dlzka) { min_dlzka = dlzka; najkratsi = i; } } return najkratsi; }
void vybaveny_zakaznik(int p, ZAKAZNIK *pokladne[N]) { ZAKAZNIK *zrus; if(pokladne[p] != NULL) { printf("Vybaveny zakaznik c. %dn", pokladne[p]->cislo); zrus = pokladne[p]; pokladne[p] = pokladne[p]->dalsi; free(zrus); } }
Rodostrom • Záznam o človeku: – – – Meno Priezvisko Ukazovateľ na záznam o matke Ukazovateľ na záznam o otcovi Počet detí Pole ukazovateľov na záznamy o ďeťoch typedef struct clovek { char meno[20]; char priezvisko[20]; struct clovek *matka; struct clovek *otec; int pocet_deti; struct clovek **deti; } CLOVEK;
CLOVEK **tety_a_strykovia(CLOVEK *clovek) { int pocet, i, j; CLOVEK **tetystr; pocet = clovek->matka->pocet_deti -1; pocet += clovek->otec->matka->pocet_deti -1; tetystr = (CLOVEK **) malloc(pocet * sizeof(CLOVEK *)); j = 0; for(i=0; i<clovek->matka->pocet_deti; i++) if(clovek->matka->deti[i] != clovek->matka) { tetystr[j] = clovek->matka->deti[i]; j++; } for(i=0; i<clovek->otec->matka->pocet_deti; i++) if(clovek->otec->matka->deti[i] != clovek->otec) { tetystr[j] = clovek->otec->matka->deti[i]; j++; } return tetystr; }
Rodostrom • Skúste premyslieť – Nájdenie všetkých bratrancov a sesterníc – Čo ak pripustíme aj nevlastných súrodencov (treba kontroľovať aj cez otca aj matku)
Procedurálne programovanie: Oddelený preklad
Oddelený preklad • vkladanie súborov – #include vznikne jeden. OBJ súbor • oddelený preklad – každý súbor sa preloží zvlášť (vznikne viac. OBJ súborov) a potom sa spoja pomocou linkeru
Príklad oddeleného prekladu vkladanie súborov: s 1. c s 2. c s 3. c oddelený preklad: s 1. c s 2. c s 3. c s. c #include "s 1. c" #include "s 2. c" #include "s 3. c" s 1. obj s 2. obj s. obj link s 1, s 2, s 3. obj
Oblasť platnosti identifikátorov • jazyk C umožňuje rôzne spôsoby ako stanoviť kde, kedy a aký identifikátor bude komu dostupný: – globálne a lokálne premenné – pamäťové triedy – typové modifikátory
Globálne premenné • organizácia v programe: globálne definície a deklarácie definície funkcií globálne definície: definujú premenné, rozsah ich platnosti: od miesta definície po koniec súboru (nie programu - program sa môže skladať z viac súborov) globálne deklarácie: deklarácie premenných, ktoré sú definované v inom súbore. často sú špecifikované slovom extern - externé deklarácie
Príklad: globálne definície int i; void prva() {. . . } premenná i je platná pre všetky 3 funkcie int j; int druha() {. . . } char *tretia() {. . . } premenná j je platná len pre funkcie: druha() a tretia()
Lokálne premenné • definované vo funkciách • platnosť lokálnych premenných: od definície po koniec funkcie int i 1, i 2; void prva() { int i 1, j 1; . . . } globálna premenná i 1 je prekrytá lokálnou premennou i 1 (používať sa môžu premenné: i 1, j 1 (lokálne) a i 2 (globálna)) int j 1, j 2; int druha(){ int i 1, j 1, k 1; . . . } dve globálne premenné: i 2, j 2 a tri lokálne premenné: i 1, j 1, k 1.
Inicializácia lokálnych a globálnych premenných • lokálne premenné: – nie sú automaticky inicializované • globálne premenné: – automaticky inicializované na 0 (0. 0, ) (lepšie - nespoliehať sa na to)
Pamäťové triedy • určujú v ktorej časti pamäte bude premenná umiestnená a kde bude viditeľná – – auto extern static register
Trieda auto • automatické premenné – – implicitne pre lokálne premenné uložená v zásobníku (stacku) existuje od vstupu do funkcie do jej konca nie je inicializovaná void func() { je auto int i; ekvivalentné auto int j = 5; } void func() { int i; int j = 5; }
Trieda extern • implicitne pre globálne premenné • uložená v dátovej oblasti • používa sa pri oddelenom preklade súborov, kde viac súborov zdiela jednu premennú – v jednom súbore je táto premenná definovaná bez kľúčového slova extern, v ostatných súboroch musí byť použité extern v súbore s 2. c v súbore s 1. c int suma; definícia extern int suma; deklarácia
Trieda static • neexistuje žiadna implicitná definícia • najčastejšie lokálne premenné (definované vo funkcii), ktoré si nechávajú svoju hodnotu medzi jednotlivými volaniami funkcie • premenná existuje od prvého volania funkcie do konca programu int f() { int x = 2; static int i = 0; printf("i: %d, x: %d n", i, x); i++; x++; } for(j = 0; j < 3; j++) f(); i: 0, x: 2 i: 1, x: 2 i: 2, x: 2
Trieda static • globálne premenné: tiež static - viditeľné len v module, kde sú definované • ak viac static premenných, radšej každú na zvlášť riadku static int i, j; static int i; static int j;
Trieda register • jazyk C - nízkoúrovňový a preto umožňuje, aby premenná bola zapísaná v registri – – ak sa dá do ktorého registra - vyberá si prekladač len lokálne premenné tie, ku ktorým je vhodné pristupovať rýchlo register int i; register int j; ak je viac premenných, označenie triedy register vyznačiť pre každú premennú zvlášť
Prílad použitia triedy register násobky čísla k void nasobilka(register int k) { register int i; for (i = 1; i <= 10; i++) printf("%2 d x %2 d = %2 d n", i, k, i * k); }
Typové modifikátory • ľubovoľná premenná nejakého dátového typu (int i) zaradená do nejakej pamäťovej triedy (napr. static) môže byť modifikovaná typovým modifikátorom: – const – volatile napríklad: static const unsigned int j = 5;
Modifikátor const • v ANSI C • po inicializácii už nemôže byť menená hodnota premennej • podobne ako konštanta (#define), len má určený typ, čo konštanta nemá (dá sa využiť ku kontrolám prekladača (napr. typ skutočných parametrov funkcie)) • najčastejšie: pri definícii formálnych parametrov funkcie parameter označený ako const je len vstupným parametrom (vo funkcii sa nemení) napríklad: int hladaj(const char *str, char co)
Modifikátor const • časté chyby: const float pi = 3. 14159; const int max = 100; chyba: max nie je konštanta int pole[max]; chyba: pi sa už nedá meniť pi = 3. 14;
Modifikátor volatile • v ANSI C • málo časté • upozorňuje prekladač, že premenná môže byť modifikovaná nejakou bližšie nešpecifikovanou asynchrónnou udalosťou (napr. pomocou prerušenia) – napr. cyklus (neobsahujúci premennú pocet), ktorý je závislý na premennej pocet a tá je menená hardverovým prerušením – ak by nebola označená modifikátorom volatile - prekladač by to mohol optimalizovať tak, že by premennú pocet nahradil jej hodnotou, akú mala pred cyklom
Príklad: modifikátor volatile int pocet; void wait(int maximum) { pocet = 0; while (pocet < maximum) ; } cyklus skončí po zmene premennej pocet nejakým hardverovým prerušením
Bloky • blok programu - uzatvorený v { } môže obsahovať definície premenných – lokálne premenné (auto, alebo static) – viditeľné sú len v bloku if (i > 0) { int i; . . . } else { double f; . . . }
Príklad oddeleného prekladu vkladanie súborov: s 1. c s 2. c s 3. c oddelený preklad: s 1. c s 2. c s 3. c s. c #include "s 1. c" #include "s 2. c" #include "s 3. c" s 1. obj s 2. obj s. obj link s 1, s 2, s 3. obj
Oblasť platnosti identifikátorov: zhrnutie • globálne a lokálne premenné • pamäťové triedy: – auto (implicitne lokálne premenné, v stacku) – extern (implicitne globálne premenné, v dátovej oblasti) – static (lokálne premenné: zachovávajú hodnotu medzi volaniami funkie, globálne premenné: platnosť v rámci jedného súboru) – register (lokálne premenné, zapísané v registri) • typové modifikátory: – const (konštantné premenné, nemenia hodnotu) – volatile (lokálne premenné, zmena hardverovým prerušením)
Oddelený preklad súborov • rozdeliť program na viac čo najmenej závislých častí • definovať rozhranie - spôsob komunikácie medzi oddelenými časťami (. h súbory) – pomocou funkcií (lepšie ako pomocou globálnych premenných viditeľných vo všetkých súboroch)
Rozšírenie platnosti globálnej premennej • globálna premenná: – definovaná v jednom súbore – deklarovaná pomocou extern v ostatných súboroch
Príklad: rozšírenie platnosti globálnej premennej definície A. c: B. c: int x; extern double f; #include <stdio. h> int fun(void) { return (x + (int) f); } deklarácie extern int x; extern int fun(void); double f; void main() { x = 3; f = 3. 5; printf("%d n", fun()); }
Statické globálne premenné a funkcie • trieda static - viditeľné len v module, v ktorom boli definované – pre globálne premenné – pre funkcie
Príklad: statické globálne premenné a funkcie A. c: B. c: static int x; extern double f; #include <stdio. h> static int fun(void) { return x; } static int funkcia(void) { return (x + (int) f); } pri linkovaní chyba: x: v A. c static v B. c len deklarácia extern int x; extern int funkcia(void); double f; static void fun(void) { prinftf("%d n", funkcia()); } void main() { x = 3; f = 3. 5; printf("%d n", fun()); }
Zdrojové a hlavičkové súbory • . c súbory - definície globálnych premenných a funkcií: – pre všetky moduly (žiadne označenie) – len pre aktuálny modul (označenie static) • . h súbory - definujú rozhranie, t. j. definujú globálne premenné a funkcie, ktoré sa používajú v iných moduloch (označenie extern) • . c súbory include-ujú len. h súbory ktoré potrebujú (nikdy ne -include-ujú. c súbory)
Ako udržať poriadok vo veľkom programe 1. 2. 3. 4. 5. 6. definície funkcií a premenných v súbore program_1. c v program_1. c - striktne rozlíšené, čo sa bude používať v rámci súboru a čo mimo neho (čo najmenej) všetky ostatné globálne premenné a funkcie označiť static funkčné prototypy zdielaných funkcií a premenných - do program_1. h, označíme ich extern ak poskytujeme aj symbolické konštanty - dáme ich len do program_1. h program_1. c začína: #include <stdio. h> #include "program_1. h"
Ako udržať poriadok vo veľkom programe 7. súbor program_2. c obsahujúci ďalší modul programu a využíva premenné, funkcie alebo konštanty z modulu program_1, začína: #include <stdio. h> #include "program_1. h" #include "program_2. h"
Odporučený obsah. c súborov 1. dokumentačná časť (meno súboru, verzie, stručný popis modulu, meno autora a dátum) 2. všetky potrebné #include len súbory. h, nie. c! najprv systémové < > a potom vlastné " " 3. deklarácie importovaných objektov (extern) len ak nie sú v. h súbore spolupracujúceho modulu (čomu dávame prednosť) - v iných moduloch sú tieto objetky bez špecifikovanej triedy 4. definície globálnych premenných premenné definované mimo funkcií zdielané inými modulmi (čo najmenej!)
Odporučený obsah. c súborov 5. lokálne #define definícia konštánt a makier len pre aktuálny modul len ak veľmi rozsiahle - do zvlášť. h 6. definície lokálnych typov typedef len pre aktuálny modul len ak veľmi rozsiahle - do zvlášť. h 7. definície premenných len pre aktuálny modul globálne len pre aktuálny modul - static 8. 9. úplné funkčné prototypy funkcií len pre aktuálny modul funkcia main() 10. definície funkcií aj pre iné moduly 11. definície funkcií len pre aktuálny modul
Odporučený obsah. h súborov 1. dokumentačná časť (meno súboru, verzie, stručný popis modulu, meno autora a dátum) 2. 3. 4. 5. 6. definície symbolických konštánt ktoré sa budú používať aj v iných moduloch definície makier s parametrami, ktoré sa budú používať aj v iných moduloch definície typov, ktoré sa budú používať aj v iných moduloch deklarácie premenných aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern) funkčné prototypy funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
Príklad: oddelený preklad • program na výpočet obsahu a obvodu kruhu: kruh_main. c, kruh_main. h, kruh_io. c, kruh_io. h globálne premenné a funkcie lokálne premenné a funkcie kruh_main double obvod double vyp_priemer(double polomer) double polomer, obsah void vyp_obsah(double polomer) doble vyp_obvod() void vypocet(void) kruh_io double polomer double vstup_dat() double vystup_dat(double obsah) premenné a funkcie definované v jednom z modulov - môžu sa používať aj v rámci druhého modulu
#include <stdio. h> #include "kruh_main. h" #include "kruh_io. h" double obvod; #define pi 3. 14; static double polomer; static double obsah; double vyp_priemer(double polomer); static void vyp_obsah (double polomer); static doble vyp_obvod(); static void vypocet(void); static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer; } static doble vyp_obvod() { return(PI*vyp_priemer(polomer)); } static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer); } void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) double vyp_priemer(double polomer) printf("Chybny polomer. "); { else { return (2 * polomer); vypocet(); } vystup_dat(obsah); glob. definície } kruh_main. c }
Hlavičkový súbor modulu kruh_main deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern) extern double obvod; extern double vyp_priemer(double polomer); kruh_main. h
#include <stdio. h> #include "kruh_io. h" #include "kruh_main. h" #define kontrola(x) ((x >= 0. 0) ? x : CHYBA_DAT) static double polomer; double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer); } glob. definície void vystup_dat(double obsah) { double priemer; printf("Obsah kruhu s polomerom %6. 2 f je %. 2 fn", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6. 2 f je %. 2 fn", polomer, obvod); } kruh_io. c
Hlavičkový súbor modulu kruh_io deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern) #define CHYBA_DAT -1 extern double vstup_dat(); extern double vystup_dat(double obsah); kruh_io. h
Oddelený preklad extern #define CHYBA_DAT -1 double obvod; double vyp_priemer(double polomer); kruh_main. h extern #include <stdio. h> static double polomer; static double obsah; static void vyp_obsah (double polomer); static doble vyp_obvod(); static void vypocet(void); void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer. "); else { vypocet(); vystup_dat(obsah); } } double vystup_dat(double obsah); kruh_io. c #include <stdio. h> #include "kruh_main. h" #include "kruh_io. h" double obvod; #define pi 3. 14; double vstup_dat(); static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer; } #include "kruh_io. h" #include "kruh_main. h" #define kontrola(x) ((x >= 0. 0) ? x : CHYBA_DAT) static double polomer; static doble vyp_obvod() { return(PI*vyp_priemer(polomer)); } double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer); } static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer); } void vystup_dat(double obsah) { double priemer; double vyp_priemer(double polomer) { return (2 * polomer); } kruh_main. c printf("Obsah kruhu s polomerom %6. 2 f je %. 2 fn", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6. 2 f je %. 2 fn", polomer, obvod); } kruh_io. c
Visual C++ a oddelený preklad • • vytvorenie projektu (Win 32 Console Application) vloženie súboru – – • C++ Source File C/C++ Header File Menu Build 1. 2. Build program. exe Compile program. exe
Procedurálne programovanie: Bitové operácie
Práca s bitmi • práca s reprezentáciou čísla v dvojkovej sústave Prevod čísla do dvojkovej sústavy • Príklady: – – 1: 2: 3: 4: 001 010 011 100 príklad prevod čísla 4: 4 / 2 = 2 zvyšok 0 2 / 2 = 1 zvyšok 0 1 / 2 = 0 zvyšok 1 Prevod čísla do dvojkovej sústavy (delenie dvomi) Zvyšky prečítané zospodu hore predstavujú číslo v dvojkovej sústave Výsledok sa použije ako delenec v nasledujúcej časti prevodu
Oprácie s jednotlivými bitmi • operátory: – & - bitový súčin (AND) – | - bitový súčet (OR) – ^ - bitový exkluzívny súčet (XOR) – << - posun doľava – >> - posun doprava – ~ - jednotkový doplnok (negácia bit po bite) • argumenty nemôžu byť float, double ani long double
Bitový súčin • i-ty bit výsledku x & y bude 1 vtedy, ak i-ty bit x aj i-ty bit y sú 1, inak 0 (AND po bitoch) #define je_neparne(x) (1 & (unsigned) (x)) & 0000 0001 xxxx xxx? 1 0 0000 000? x 0 0 1 1 y 0 1 x&y 0 0 0 1 • ak chceme premennú typu int použiť ako ASCII znak, teda potrebujeme najmenších 7 bitov 0000 0111 1111 = 0 x 7 F c = c & 0 x 7 F; c &= 0 x 7 F;
Rozdiel medzi bitovým a logickým súčin unsigned int i = 1, j = 2, k, l; k = i && j; l = i & j; • k: 1, pretože 1 a 2 sú kladné číla, teda majú logickú hodnotu true (pravda) a && je logický súčin • l: 0, pretože 1 = 0000 0001 2 = 0000 0010 a & je bitový súčin
Bitový súčet • i-ty bit výsledku x | y bude 1 vtedy, ak i-ty bit x alebo i-ty bit y sú 1, inak 0 (OR po bitoch) • používa sa na nastavenie niektorých bitov na jednotku, pričom nechá ostatné bity nezmenené #define na_neparne(x) (1 | (unsigned) (x)) | 0000 0001 xxxx xxx? 1 0 1 xxxx xxx? x 0 0 1 1 y 0 1 x|y 0 1 1 1 makro vráti nepárne číslo nezmenené a párne zväčší o 1
Bitový exkluzívny súčet • i-ty bit výsledku x ^ y bude 1 vtedy, ak sa i-ty bit x nerovná i-temu bitu y, inak 0 (XOR po bitoch) if (x ^ y) /* cisla sú rozdielne */ x 0 0 1 1 y 0 1 x^y 0 1 1 0
Bitový posun doľava • x << n posunie bity v x o n pozícií doľava • bity zľava sa strácajú bity zprava sú dopĺňané nulami x = x << 1; na rýchle násobenie dvomi x = 0001 1011 0010 0101 = 6949 x << 1 = 0011 0110 0100 1010 = 13898 = 2 * 6949 x = x << 3; vynásobesnie 23 = 8
Bitový posun doprava • x >> n posunie bity v x o n pozícií doprava • bity zprava sa strácajú bity zľava sú dopĺňané nulami x = x >> 1; na rýchle celočíselné delenie dvomi x = 0011 0110 0100 1010 = 13898 x >> 1 = 0001 1011 0010 0101 = 6949 = 13898 / 2 x = x >> 3; celočíselné delenie 23 = 8
Príklad: delenie a násobenie • bitové posuny sú rýchlejšie ako násobenie a delenie násobkami dvojky i = j * 80; i = (j << 6) + (j << 4); 80 = 64 + 16 rýchlejšie
Príklad: zistenie hodnoty konkrétneho bitu vráti hodnotu iteho bitu x #define ERROR -1 #define CLEAR 1 #define BIT_V_CHAR 8 int bit(unsigned x, unsigned i) { if (i >= sizeof(x) * BIT_V_CHAR) return (ERROR); else return ((x >> i) & CLEAR); } 1 0010 0101 0010 1 1001 0001 1001 0010 1 0100 0000 1100 1001 0000 0110 0100 11010 1 0000 0011 0010 0101 1 0000 0001 1001 0010 1 0000 1100 1001 & 0000 0000 0001
Negácia po bitoch • jednotkový doplnok ~x • prevráti nulové bity na jednotkové a naopak • Použitie napr. ak sa chceme vyhnúť na počítači závislej dĺžke celého čísla: x &= 0 x. FFF 0; x &= ~0 x. F; nastavenie posledných 4 bitov na nulu - len ak platí sizeof(int) == 2 nastavenie posledných 4 bitov na nulu - platí pre všade
Príklad Zistenie dĺžkyky typu int v bitoch #include <stdio. h> int dlzka_int() { unsigned int x, i = 0; x = ~0; /* negácia 0 -> same 1 */ while ((x >> 1) != 0) i++; return (++i); } int main() { printf("Dlzka typu int je %d bitovn", dlzka_int()); return 0; }
Práca so skupinou bitov • stavová premenná stav - definuje práva na prístup k súboru #define READ 0 x 8 #define WRITE 0 x 10 #define DELETE 0 x 20 READ: 23 = 0000 0100 WRITE: 24 = 0000 1000 DELETE: 25 = 0001 0000 unsigned int stav; stav |= READ | WRITE | DELETE; stav |= READ | WRITE; stav &= ~(READ | WRITE | DELETE); stav & = ~READ; if ( ! (stav & (WRITE | DELETE))). . . nastaví 2. , 3. a 4. bit na 1 nastaví 2. , 3. a 4. bit na 0 nastaví 2. bit na 0 ak 2. a 3. bit sú nulové
Bitové pole • štruktúra, ktorej veľkosť je obmedzená veľkosťou typu int • najmenšia dĺžka položky je 1 bit • definuje podobne ako štruktúra, ale každá položka bitového poľa je určená menom a dĺžkou v bitoch • môže byť signed aj unsigned (preto vždy uviesť) • oblasti použitia: – uloženie viac celých čísel v jednom (šetrenie pamäte) – pre prístup k jednotlivým bitom (často)
Príklad bitového poľa • uloženie dátumu do jednotho int-u: – deň - najmenších 5 bitov, – mesiac - ďalšie 4 bity, – rok - zvyšných 7 bitov (max. 127, preto rok - 1980) typedef struct { unsigned den unsigned mesiac unsigned rok } DATUM; bity 0 -4 : 5; : 4; : 7; DATUM dnes, zajtra; dnes. den = 29; dnes. mesiac = 11; dnes. rok = 2012 - 1980; zajtra. den = dnes. den + 1; bity 5 -8 bity 9 -15
Príklad bitového poľa Dátum ako bitové pole aj hexadecimálne číslo (union) #include <stdio. h> typedef struct { unsigned den : 5; unsigned mesiac : 4; unsigned rok : 7; } DATUM; typedef union { DATUM datum; unsigned int cislo; } BITY; /* bity 0 - 4 */ /* bity 5 - 8 */ /* bity 9 - 15 */
Príklad bitového poľa pokračovanie int main(void) { BITY dnes; int d, m, r; #include <stdio. h> typedef struct { unsigned den unsigned mesiac unsigned rok } DATUM; typedef union { DATUM datum; unsigned int cislo; } BITY; printf("Zadaj dnesny datum [dd mm rrrr]: "); scanf("%d %d %d", &d, &m, &r); dnes. datum. den = d; dnes. datum. mesiac = m; dnes. datum. rok = r - 1980; printf("datum: %2 d. %4 d - cislo: %X hexan", dnes. datum. den, dnes. datum. mesiac, dnes. datum. rok + 1980, dnes. cislo); return 0; } : 5; : 4; : 7;
- Slides: 70