Upload
maude
View
87
Download
3
Embed Size (px)
DESCRIPTION
Procedur álne programovanie: 9 . prednáška. Gabriela Kosková. Obsah. príklady k štruktúram a ukazovateľom (2) oddelen ý preklad b itov é operácie a polia. Príklad: simulácia pokladní v obchode. N pokladní v obchode Pri každej pokladni – rad zákazníkov. ZAKAZNIK *pokladne[N];. - PowerPoint PPT Presentation
Citation preview
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
• Pri každej pokladni – rad zákazníkov
typedef struct zakaznik { int cislo; struct zakaznik *dalsi;} ZAKAZNIK;
ZAKAZNIK *pokladne[N];
• 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]);
void odchod_zakaznika(int cislo, ZAKAZNIK *pokladne[N]);int main();
• Námety na zamyslenie
• 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. %d\n", 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->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->matka->pocet_deti; i++) if(clovek->matka->matka->deti[i] != clovek->matka) { tetystr[j] = clovek->matka->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
s2.cs1.c s3.c s1.c s2.c s3.c
s.c
#include "s1.c"
#include "s2.c"
#include "s3.c"
s.obj
s1.obj s2.obj s3.obj
link s link s1, s2, s3
vkladanie súborov: oddelený preklad:
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(){...}
int j;
int druha(){...}
char *tretia(){...}
premenná i je platná pre všetky 3 funkcie
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 i1, i2;
void prva() {int i1, j1;...}
int j1, j2;
int druha(){int i1, j1, k1;...}
globálna premenná i1 je prekrytá lokálnou premennou i1 (používať sa môžu premenné: i1, j1 (lokálne) a i2 (globálna))
dve globálne premenné: i2, j2 a tri lokálne premenné: i1, j1, k1.
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, \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(){ auto int i; auto int j = 5;}
je ekvivalentné
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
int suma;
v súbore s1.c
definícia
extern int suma;
v súbore s2.c
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: 2i: 1, x: 2i: 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 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
void nasobilka(register int k){ register int i;
for (i = 1; i <= 10; i++) printf("%2d x %2d = %2d \n", i, k, i * k);}
násobky čísla 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
static const unsigned int j = 5;
napríklad:
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í)
int hladaj(const char *str, char co)
napríklad:
Modifikátor const
const float pi = 3.14159;const int max = 100;
int pole[max];
pi = 3.14;
• časté chyby:
chyba: pi sa už nedá meniť
chyba: max nie je konštanta
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
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
s2.cs1.c s3.c s1.c s2.c s3.c
s.c
#include "s1.c"
#include "s2.c"
#include "s3.c"
s.obj
s1.obj s2.obj s3.obj
link s link s1, s2, s3
vkladanie súborov: oddelený preklad:
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
int x;extern double f;
int fun(void) { return (x + (int) f);}
#include <stdio.h>
extern int x;extern int fun(void);
double f;
void main(){ x = 3; f = 3.5; printf("%d \n", fun());}
A.c: B.c:
definície
deklarácie
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
static int x;extern double f;
static int fun(void) { return x;}static int funkcia(void) { return (x + (int) f);}
#include <stdio.h>
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());}
A.c: B.c:
pri linkovaní chyba:x: v A.c static v B.c len deklarácia
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. definície funkcií a premenných v súbore program_1.c
2. v program_1.c - striktne rozlíšené, čo sa bude používať v rámci súboru a čo mimo neho (čo najmenej)
3. všetky ostatné globálne premenné a funkcie označiť static
4. funkčné prototypy zdielaných funkcií a premenných - do program_1.h, označíme ich extern
5. ak poskytujeme aj symbolické konštanty - dáme ich len do program_1.h
6. 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 #definedefinícia konštánt a makier len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
6. definície lokálnych typovtypedef len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
7. definície premenných len pre aktuálny modulglobálne len pre aktuálny modul - static
8. úplné funkčné prototypy funkcií len pre aktuálny modul
9. 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. definície symbolických konštánt ktoré sa budú používať aj v iných moduloch
3. definície makier s parametrami, ktoré sa budú používať aj v iných moduloch
4. definície typov, ktoré sa budú používať aj v iných moduloch
5. deklarácie premenných aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
6. funkčné prototypy funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
Príklad: oddelený preklad
globálne premenné a funkcie
lokálne premenné a funkcie
kruh_main double obvod
double
vyp_priemer(double
polomer)
double polomer, obsahvoid vyp_obsah(double polomer)doble vyp_obvod()void vypocet(void)
kruh_io double vstup_dat()double vystup_dat(double obsah)
double polomer
• program na výpočet obsahu a obvodu kruhu:
kruh_main.c, kruh_main.h, kruh_io.c, kruh_io.h
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);
void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer."); else { vypocet(); vystup_dat(obsah); }}
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);}
double vyp_priemer(double polomer) { return (2 * polomer);}
kruh_main.cglob. definície
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
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)
#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);}
void vystup_dat(double obsah) { double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", polomer, obvod);}
glob. definície
kruh_io.c
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah);
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)
kruh_io.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);}
void vystup_dat(double obsah) { double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", polomer, obvod);}
kruh_io.c
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);}
double vyp_priemer(double polomer) { return (2 * polomer);}
#include <stdio.h>
#include "kruh_main.h"#include "kruh_io.h"
double obvod;#define pi 3.14;
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); }} kruh_main.c
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah); kruh_io.c
Oddelený preklad
Visual C++ a oddelený preklad
• vytvorenie projektu
(Win32 Console Application)
• vloženie súboru– C++ Source File
– C/C++ Header File
• Menu Build1. Build program.exe
2. Compile program.exe
Procedurálne programovanie:Bitové operácie
Práca s bitmi
• práca s reprezentáciou čísla v dvojkovej sústave
• Príklady:– 1: 001– 2: 010– 3: 011– 4: 100
Prevod čísla do dvojkovej sústavy -
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)
Výsledok sa použije ako delenec v nasledujúcej časti
prevodu
Zvyšky prečítané zospodu hore
predstavujú číslo v dvojkovej sústave
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 0000 0000 0001xxxx xxxx xxxx xxx?&
0000 0000 0000 000?0
01
1
• ak chceme premennú typu int použiť ako ASCII znak, teda potrebujeme najmenších 7 bitov
0000 0000 0111 1111 = 0x7F c &= 0x7F;c = c & 0x7F;
x y x&y0 0 00 1 01 0 01 1 1
Rozdiel medzi bitovým a logickým súčin
• k: 1, pretože 1 a 2 sú kladné číla, teda majú logickú hodnotu true (pravda) a && je logický súčin
unsigned int i = 1, j = 2, k, l;k = i && j;l = i & j;
• 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 0000 0000 0001xxxx xxxx xxxx xxx?|
xxxx xxxx xxxx xxx?1
01
1
makro vráti nepárne číslo nezmenené a párne zväčší o 1
x y x|y0 0 00 1 11 0 11 1 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 y x^y0 0 00 1 11 0 11 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;
x = 0001 1011 0010 0101
x << 1 = 0011 0110 0100 1010
= 6949
= 13898 = 2 * 6949
na rýchle násobenie dvomi
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;
x = 0011 0110 0100 1010
x >> 1 = 0001 1011 0010 0101
= 13898
= 6949 = 13898 / 2
na rýchle celočíselné delenie dvomi
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
0000 0000 1100 10011
Príklad: zistenie hodnoty konkrétneho bitu
#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);}
0011 0010 0101 00101
0001 1001 0010 10011
0000 1100 1001 01001
0000 0110 0100 10101
0000 0011 0010 01011
0000 0001 1001 00101
0000 0000 1100 10011
& 0000 0000 0000 0001
0000 0000 0000 0001
vráti hodnotu i-teho bitu x
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 &= 0xFFF0;
x &= ~0xF;
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
#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 bitov\n", dlzka_int()); return 0;}
Zistenie dĺžkyky typu int v bitoch
Práca so skupinou bitov
#define READ 0x8#define WRITE 0x10#define DELETE 0x20
unsigned int stav;
stav |= READ | WRITE | DELETE;stav |= READ | WRITE;stav &= ~(READ | WRITE | DELETE);stav & = ~READ;if ( ! (stav & (WRITE | DELETE))) ...
• stavová premenná stav - definuje práva na prístup k súboru
READ: 23 = 0000 0100 WRITE: 24 = 0000 1000 DELETE: 25 = 0001 0000
nastaví 2., 3. a 4. bit na 1
nastaví 2., 3. 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
typedef struct { unsigned den : 5; unsigned mesiac : 4; unsigned rok : 7;} DATUM;
DATUM dnes, zajtra;dnes.den = 29;dnes.mesiac = 11;dnes.rok = 2012 - 1980;zajtra.den = dnes.den + 1;
• 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)
bity 0-4
bity 5-8
bity 9-15
Príklad bitového poľa
#include <stdio.h>
typedef struct { unsigned den : 5; /* bity 0 - 4 */ unsigned mesiac : 4; /* bity 5 - 8 */ unsigned rok : 7; /* bity 9 - 15 */} DATUM;
typedef union { DATUM datum; unsigned int cislo;} BITY;
Dátum ako bitové pole aj hexadecimálne číslo (union)
Príklad bitového poľa - pokračovanie
int main(void){ BITY dnes; int d, m, r;
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: %2d.%2d.%4d - cislo: %X hexa\n", dnes.datum.den, dnes.datum.mesiac, dnes.datum.rok + 1980, dnes.cislo); return 0;}
#include <stdio.h>
typedef struct { unsigned den : 5; unsigned mesiac : 4; unsigned rok : 7;} DATUM;
typedef union { DATUM datum; unsigned int cislo;} BITY;