- práce se strukturami - bitové operace - bitová pole

Slides:



Advertisements
Podobné prezentace
A1PRG - Programování – Seminář Ing. Michal Typová konverze, oblast platnosti, paměťové třídy 9 Verze
Advertisements

Standardní knihovní funkce pro práci s textovými řetězci
VISUAL BASIC Práce s řetězci Použitá literatura: Kvoch: Visual Basic 4.
Vlastní skript může být umístěn: v hlavičce stránky v těle stránky
Programovací jazyk C++
Přednáška 11 Jiří Šebesta
Programování funkcí v Excelu
Programování 2 Cvičení 5.
25/08/20141 Typ struktura (1) Datový typ struktura ( struct ) je agrego- vaný heterogenní datový typ Jedná se o skupinu několika proměnných, které mohou.
Třída Array Je součásti balíčku java.util Účelem je usnadnit práci s poli Metody – nejpoužívanější equel(),fill(),sort() a binarySearch() equels() Slouží.
Pole, ukazatele a odkazy
BLIŽŠÍ POHLED NA TŘÍDY, DĚDIČNOST - úvod
Algoritmy I. Cvičení č. 10.
Programování v Pascalu Přednáška 8
Cvičení 2 Proměnné(jednoduché a složené) a konstanty První program Zápis výrazů.
Programování v C++ Cvičení.
Algoritmy I Cvičení č. 4.
Algoritmizace a programování
Druhé cvičení Vytváření identifikátorů Datové typy
8. přednáška typedef - preprocesor Studijní materiály najdete na adrese:
Operátory (1. část) 3 A1PRG - Programování – Seminář
Datové struktury. 2 Co je datová struktura v C datový typ složený z jiných datových typů nejjednodušší datová struktura je pole. všechny jeho prvky jsou.
Datové typy 6 A1PRG - Programování – Seminář
Jednoduché datové typy
A1PRG - Programování – Seminář Ing. Michal Operátory (2. část) 4 Verze
Seminář C cvičení STL, Trolltech Ing. Jan Mikulka.
Objektové programování
DEKLARACE PROMĚNNÝCH A KONSTANT
A1PRG - Programování – Seminář Ing. Michal Ukazatele a pole 10 Verze
Další abstraktní datové typy
Počítače a programování 1
JavaScript Podmínky, cykly a pole.
Cvičení.
KIV/PPA1 cvičení 8 Cvičící: Pavel Bžoch. Osnova cvičení Objekty v Javě Třída Konstruktor Metody Metody a proměnné třídy x instance Program sestávající.
Algoritmizace a programování Binární soubory - 14 Mgr. Josef Nožička IKT Algoritmizace a programování
Příklady v jazyku C – část 3
C# - předávání parametrů Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
IB111 Programování a algoritmizace
Spojové struktury BI-PA1 Programování a algoritmizace 1, ZS
STRING A UKAZATELE. Co to je řetězec? Řetězec v Javě je samostatný objekt. Je konstantní, co znamená, že jednou vytvořený řetězec nelze změnit. Chceme-li.
Počítače a programování 1 7.přednáška. Základy Pole ve třídách a metodách Pole Arrays.
Vazby dynamických proměnných,databázové systémy Přednáška č. 10.
Ukazatele, řetězce Přednáška č. 3. Ukazatele  Ukazatel (pointer) – typ o velikosti 4 bajty (v 32bit. systémech) pro uložení adresy objektu na který ukazuje.
Soubory BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
Vícerozměrná pole (1) Jazyk C povoluje, aby pole mělo více rozměrů (dimenzí) než jeden Z vícerozměrných polí bývá nejčastěji použí-váno pole dvourozměrné.
Podprogramy (subroutines) Pojmenované kousky programu, které –tvoří logicky ucelené části –se v programu opakují Jsou zapsány na jednom místě a v případě.
Pokročilé datové typy (struktury, unie, dynamické proměnné)
Programování v jazyce C++
Programování KONSTANTY, ČTENÍ PO JEDNOM ZNAKU GETCHAR() FORMÁTOVANÝ VÝSTUP POMOCÍ PRINTF, VÝVOJOVÉ DIAGRAMY, CYKLY.
Programování ÚVOD, PROMĚNNÉ, OPERÁTORY A PODMÍNĚNÝ PŘÍKAZ ERIK KRÁL.
Programování OPERÁTOR SIZEOF, FUNKCE, POLE JAKO PARAMETRY FUNKCÍ ERIK KRÁL.
Programování v jazyce C++ Speciality jazyka C++, úvod do OOP.
Typ struktura (1) Datový typ struktura (struct) je agrego-vaný heterogenní datový typ Jedná se o skupinu několika proměnných, které mohou mít různé datové.
Programování ENUM, SWITCH,pole jednorozměrná a vícerozměrná, deklarace, inicializace, kopírování, porovnání Erik Král.
Vícerozměrná pole (1) Jazyk C povoluje, aby pole mělo více rozměrů (dimenzí) než jeden Z vícerozměrných polí bývá nejčastěji použí-váno pole dvourozměrné.
Výukový materiál zpracován v rámci projektu
Programovací jazyk C++
Programovací jazyk C Autorem materiálu a všech jeho částí, není-li uvedeno jinak, je Ing. Jitka Vlčková. Dostupné z Metodického portálu ISSN.
Struktury.
Programování v jazyce C++
Funkce výstupu (2) Funkce printf: deklarována v: stdio.h
Abstraktní datové typy
Lexikální atomy jazyka C
Dynamické proměnné (1) Proměnné, jejichž počet a (nebo) velikost pa-měti využívané těmito proměnnými se v prů-běhu programu mění Dynamické proměnné lze.
Oblast platnosti identifikátoru (1)
Typ pole (1) Proměnná typu pole představuje kolekci proměnných stejného datového typu, které mohou být označovány společným jménem (identifikátorem) Pole.
Proměnné (1) Proměnná: Definice proměnných:
Union neboli sjednocení Bitová pole
Union neboli sjednocení Bitová pole
Transkript prezentace:

7. přednáška http://www.uai.fme.vutbr.cz/~vdumek/ 20. 3. 2008 - práce se strukturami - bitové operace - bitová pole - uniony (sjednocení) Studijní materiály najdete na adrese: http://www.uai.fme.vutbr.cz/~vdumek/

Struktury - oba způsoby lze libovolně kombinovat struct { struct STRU { int k1, k2; float h, z; char *buf1; char pole[10]; } to_to; }; - oba způsoby lze libovolně kombinovat struct STRU s1, s2, s3; struct STRU { float h, z; char pole[10]; } a, b, c; - struktury lze při deklaraci inicializovat (podle K&R pouze externí a statické) { deklarace struktury} = { seznam inicializatoru };

Struktury struct { int a, b; char *c; int pole[5]; double d; } upoc = { 1, 2, “TEXT”, {1, 3, 5, 7, 9}, 3.141312 }; typedef struct { char jmeno[25]; cgar trida; short podtrida; float dekl, rekt, vzdal; } hvezda; main() { hvezda moje_hvezda; strcpy(moje_hvezda.jmeno, “epsilon eridani”); moje_hvezda.trida = ‘K‘; moje_hvezda.podtrida = 4 ….. }

Příklady struktur struct { int vyska; float vaha; } pavel, honza, karel; struct miry { int vyska; float vaha; } pavel, honza, karel; typedef struct { int vyska; float vaha; } MIRY; MIRY pavel, honza, karel; struct miry { int vyska; float vaha; }; struct miry pavel; struct miry honza, karel; pozor, nelze !!! miry pavel, honza, karel; typedef struct miry{ int vyska; float vaha; } MIRY; MIRY pavel, honza, karel;

Struktury - jméno struktury je nepovinné, slouží pouze jako identifikátor šablony - je-li jméno nadefinováno, používáme je k pozdější deklaraci - nejsou-li při deklaraci specifikovány proměnné typu struktura, vytvoří se jen šablona se jménem - proměnné strukturovaných typů, které nemají jmenovku, nemůžeme předávat jako parametr funkce. - strukturu můžeme i inicializovat - do složených závorek napíšeme seznam hodnot proměnných obsažených ve struktuře - nemusíme inicializovat všechny prvky, lze vynechat prvky na konci struktury - struktury lze navzájem vnořovat (struktura nemůže obsahovat proměnnou svého vlastního typu)

Práce se strukturami - stejně jako u proměnných máme možnost deklarovat směrník na strukturu, je pro něj zaveden operátor ->, přináší možnost řetězit struktury, členem struktury nesmí být struktura stejného typu, přípustný je pouze směrník struct MOJE { float a, b; int c; char *smer; }; struct MOJE da_da; struct MOJE *sm_moje; …….. sm_moje = calloc(1, sizeof(struct MOJE)); struct TADY { struct TADY { ….. …… struct TADY a; struct TADY *a; …… ……. }; }; NE ANO

Ukazatel na strukturu - ukazatel na strukturu typedef struct { char jmeno[30]; int rocnik; } STUDENT; STUDENT s, *p_s; - alokování paměti: p_s = (STUDENT *) malloc(sizeof(STUDENT)); - inicializace směrníku: p_s = &s; - definice typu směrník na strukturu: } STUDENT, *P_STUDENT; STUDENT s; P_STUDENT p_s; p_s = (P_STUDENT) malloc(sizeof(STUDENT));

Struktury - přístup k prvkům struktury, operátor . zpřístupňuje proměnné ze struktury - operátor -> zpřístupňuje proměnné ze struktury, na kterou máme ukazatel pavel.vyska = 190; pavel.vaha = karel.vaha; struct miry *p_karel; p_karel = &karel; p_karel->vyska = 184; (*p_karel).vyska = 184; často používáme pole struktur, nebo dynamické datové typy vytvořené jako spojové seznamy ze struktur - například binární strom: struct tree { struct tree *left; /* struct tree { struct tree b; … */ struct tree *right; } a;

Práce se strukturami - zpřístupnění prvku struktury se provádí přes proměnnou, nebo přes směrník da_da.a = 5.46; da_da.c = 3; da_da.b = da_da.a / da_da.c; sm_moje->a = 6.78; sm_moje->c = 7; sm_moje->b = sm_moje->a / sm_moje->c; sm_moje->smer = calloc(100, sizeof(char)); - další operace pro struktury jsou: získání adresy, přiřazení struktur stejného typu, parametr, návratová hodnota funkce - pro získání adresy se používá operátor &, deklarovaný směrník musí být generický nebo na strukturu stejného typu - jako parametr i návratová hodnota mohou být i směrníky na strukturu

Práce se strukturami

Práce se strukturami struct XXX { p=&v; /* ziskani adresy */ int a, b, c; x=v; /* prirazeni struktur */ float d; } v, x, *y; struct XXX fce(struct XXX m) { struct XXX z; struct XXX *p; ….. return z; } - v dalším příkladu nejsou struktury a, m, n formálně shodné, nel- ze je proto přiřazovat struct SSSR { struct { float b, f; float b, f; }; } a; struct SSSR m, n; - kompilátory pro normu ANSI mají možnost nastavit zarovnávání ukládání struktury na hranici slova, každá struktura potom začí- ná na sudé adrese, každý člen struktury jiného typu než char bude mít sudou relativní adresu vzhledem k začátku struktury

Práce se strukturami struct person { struct date { char name[NAMESIZE]; char addr[ADDRSIZE]; long zipcode; double salary; struct date birthdate; struct date hiredate; }; struct date { int day; int month; int year; int yesterday; char mon_name[4]; }; … struct person KAREL; KAREL.birthdate.month /* odkaz na měsíc narození */ /* operátor kvalifikace se sdružuje*/ /* zleva doprava*/

Práce se strukturami struct { /* ++p->x inkrementuje x, nikoliv p, neboť */ int x; /* priorita zajistí provedení ++(p->x) */ int y; } *p; /* pro jiné vyhodnocení musíme změnit prioritu, */ /* (++p)->x inkrementace před dosažením x */ /* (p++)->x inkrementace po dosažení x */ struct { int *x; int *y; } *m; *m->y obsah místa, kam ukazuje y *m->x++ inkrementuje x po přístupu k místu, kam ukazuje (*p->y)++ inkrementuje obsah místa, kam ukazuje y p++->x inkrementuje p po přístupu k místu, kam ukazuje x

#include <stdio.h> #include <string.h> #define ZNAKU_NAZEV 25 #define POLOZEK_ZBOZI 10 #define FORMAT_VYROBEK "cislo:%5d pocet:%5d cena:%10.2f nazev:%s\n" typedef struct {float re, im;} complex; typedef struct { int ev_cislo; char nazev[ZNAKU_NAZEV + 1]; int na_sklade; float cena; } vyrobek; typedef vyrobek zbozi[POLOZEK_ZBOZI]; int main(void) { complex cislo, im_jednotka = {0, 1}; zbozi polozky; vyrobek *ppolozky, a = {8765, "nazev zbozi na sklade", 100, 123.99}; cislo.re = 12.3456; cislo.im = -987.654; polozky[0].ev_cislo = 0; strcpy(polozky[0].nazev, "polozka cislo 0"); polozky[0].na_sklade = 20; polozky[0].cena = 45.15;

ppolozky = polozky + 1; ppolozky->ev_cislo = 1; /* (*ppolozky).ev_cislo = 1; */ strcpy(ppolozky->nazev, "polozka cislo 1"); ppolozky->na_sklade = 123; ppolozky->cena = 9945.15; printf("re = %10.5f im = %10.5f\n", im_jednotka.re, im_jednotka.im); printf("re = %10.5f im = %10.5f\n", cislo.re, cislo.im); printf(FORMAT_VYROBEK, a.ev_cislo, a.na_sklade, a.cena, a.nazev); printf(FORMAT_VYROBEK, polozky[0].ev_cislo, polozky[0].na_sklade, polozky[0].cena, polozky[0].nazev); printf(FORMAT_VYROBEK, ppolozky->ev_cislo, ppolozky->na_sklade, ppolozky->cena, ppolozky->nazev); return 0; } Výstup získaný spuštěním programu: re = 0.00000 im = 1.00000 re = 12.34560 im = -987.65399 cislo: 8765 pocet: 100 cena: 123.99 nazev:nazev zbozi na sklade cislo: 0 pocet: 20 cena: 45.15 nazev:polozka cislo 0 cislo: 1 pocet: 123 cena: 9945.15 nazev:polozka cislo 1

Bitové operace & bitový součin | bitový součet ^ bitový exklusivní součet << posun doleva >> posun doprava ~ jedničkový doplněk

Bitová pole - pokud potřebujeme do jednoho slova uložit více než jeden objekt, používáme bitová pole, bitové pole je množina sousedních bitů v rámci proměnné typu int deklarace a použití takových proměnných je stejné jako u struktur, pouze u jednotlivých proměnných používáme operátor : pro stanovení počtu jednotlivých bitů struct flags { unsigned a:1; :2; /* zarovnání */ unsigned b:1; unsigned c:3; } flag; flag.a = 1; /* použití */ vynecháme-li jméno bitového pole, použijeme vyhrazené bity pouze jako výplň pro zarovnání specifická délka 0 se používá pro zarovnání na slovo bitové pole musí být typu int, signed int nebo unsigned int jednotlivé proměnné uvnitř bitového pole nemají své adresy bitová pole většinou nevedou k ušetření paměti (více instrukcí, ...)

Bitová pole bitový součin - & 77 & 198 = 68 1001101 & 11000110 = 01000100 Operandy operátoru binárního součinu mohou být pouze výrazy celočíselného typu, není tedy možné provádět bitový součin s hodnotami typu float, double ani long double. #define liche(x) (1 & (x)) makro pro určení lichosti a sudosti bitový součet - | 77 | 198 = 207 1001101 | 11000110 = 11001111 bitový exklusivní součet - ^ 77 ^ 198 = 139 1001101 ^ 11000110 = 10001011 bitová negace - ~ Na rozdíl od předchozích operátorů je bitová negace unárním operátorem, tedy má pouze jeden operand. Ten musí být, stejně jako v předchozích případech, celočíselného typu. Při provádění operace jsou postupně všechny jeho bity negovány a takto získaná hodnota je výsledkem použití operátoru. V následujícím příkladu uvažujeme typy unsigned char. V případě použití typu signed by ještě hrál roli negovaný znaménkový bit.

Bitová pole ~77 = 178 01001101 10110010 Protože jsou negovány všechny bity čísla, včetně počátečních nul, znamená to, že pro operandy se stejnou hodnotou, ale různým typem (char, short, int, long int), bude výsledná hodnota různá. bitový posun doleva - << Při posunu se bity nejvíce nalevo ztrácejí a zprava jsou uvolněná místa doplněna nulami. Následující příkaz vrátí o dvě místa bitově posunutou hodnotu čísla 45. 45 << 2; před posunem (hodnota 45) 00101101po posunu (hodnota 180, výsledek celého výrazu) 10110100 Bitový posun doleva se často používá k provádění násobení mocninami dvou. Tento způsob je totiž znatelně rychlejší než normální násobení. Platí, že x << n = x*2n. Schopnější překladače dnes již samy nahrazují obyčejné násobení bitovým posunem. bitový posun doprava - >> Komplementární operací k bitovému posunu doleva je bitový posun doprava. V tomto případě se bity zprava ztrácí a zleva jsou doplňovány nulou u neznaménkových typů, nebo znaménkovým bitem u typů znaménkových, což je ale implementačně závislé. Stejně jako se dal bitový posun doleva použít k násobení, lze zase bitový posun doprava použít k celočíselnému dělení mocninami dvou. x >> n = x/2n 48 >> 4 = 3

Bitová pole - jde o zvláštní případ členu struktury, může být znamémkové, bezznaménkové, implicitní chápání bezznaménkovosti závisí na impementaci kompilátoru, je tedy lepší explicitně určit typ signed nebo unsigned - délka bitového pole může být 1 až 16 bitů, nevyužité bity zůstávají jako rezerva, nevztahuje se na ně zarovnávání na hranici slova - bitové pole může být pouze členem struktury, struktura s bitovým polem může obsahovat i členy běžného typu typ [identifikator] : sirka; typ - char, unsigned char, int, unsigned int identifikator - jméno pro skupinu bitů, pokud je vynechán, jsou bity rezervovány sirka - pocet bitů pro danou skupinu

Bitová pole - hodnoty jsou ukládány ve dvojkovém doplňkovém kódu s inter- pretací závislou na znaménkovosti struct POLE_BITU { Dosažitelnost prvků int i : 2; my_my.i = 1; unsigned j : 5; my_my.j = 23; int : 4; my_my.k = 0; int k : 1; my_my.m = -1; int m : 4; } my_my; 15 14 13 12 11 3 4 10 6 9 8 7 5 2 1 - -1 -- 23 m k nepoužito j i - používání bitových polí může přinášet problémy s portabilitou programů, detaily ukládání jsou implementačně závislé - nelze získat adresu bitového pole

Bitová pole #define KEYWORD 01 #define EXTERNAL 02 #define STATIC 04 ... flags |= EXTERNAL | STATIC; /* nastaví bity EXTERNAL a STATIC */ flags &= ~(EXTERNAL | STATIC); /* vynuluje bity EXTERNAL a STATIC */ if((flags & (EXTERNAL | STATIC)) == 0 … /* splněná podmínka pro vynulované */ struct { unsigned KEYWORD : 1; unsigned EXTERNAL : 1; unsigned STATIC : 1; } flags; flags.EXTERN = flags.STATIC = 1; /* nastavení bitů */ flags.EXTERN = flags.STATIC = 0; /* vynulování bitů*/ if(flags.EXTERN == 0 && flags.STATIC == 0) ... /* testování */

Uniony - union je datový typ, který má několik prvků různých typů, ale programátor může používat vždy jen jeden z nich, tyto prvky leží v paměti na jednom místě, velikost unionu odpovídá velikosti největšího prvku - union šetří místo v paměti, pokud programátor ví, že bude potřebovat pouze jeden prvek, ale neví, jakého typu, při nepovinné inicializaci uvádíme ve {} hodnotu příslušnou prvnímu typu - přístup k prvkům unionu, operace s uniony jsou stejné jako u struktur, uniony mohou být součástí polí a struktur a opačně union jmeno { int ival; float fval; char *pval; } a; - pokud chceme šablonu použít později: union jmeno

Uniony - sjednocení, slouží k ukládání složek různého datového typu na jedno místo paměti, složky netvoří celou proměnnou, v jednom okamžiku je proměnná tvořena vždy jedním ze členů. K jednomu paměťovému místu tak lze přistupovat různým způsobem struktura: char + int + float = 7 B union: char + int + float = 4 B - deklarace unionu má tvar: union jmenovka {<seznam slozek> } promenna; - význam jednotlivých deklarátorů je shodný se strukturami

Uniony - bitové pole už smí být členem unionu, všechny členy unionu se ukládají od stejné adresy a překrývají se, velikost unionu je tedy dána velikostí největší složky - opět není povoleno vkládání unionů stejného typu do sebe, opět se řeší pomocí směrníku promenna_union.slozka smernik_union -> slozka union znamenko { long znam; /* 4 B, n.znam */ unsigned long bez_znam; /* 4 B, n.bez_znam */ } n; struct { char jmeno[30]; enum {muz, zena} pohlavi; union { enum {ne, ano} vojak; /* zamestnanec.zdata.vojak */ char rozena[20]; } zdata; /* zamestnanec.zdata.rozena */ } zamestnanec;

Uniony

Uniony - použití unionu pro simulaci registrů procesoru (DOS.H) struct BYTEREGS { unsigned char al, ah, bl, bh; unsigned char cl, ch, dl, dh; }; struct WORDREGS { unsigned int ax, bx, cx, dx; unsigned int si, di, cflag, flags; union REGS { struct WORDREGS x; struct BYTEREGS h; void main(void) { union REGS TAMARA; ….. TAMARA.h.al = 0x34; TAMARA.h.ah = 0x12; printf(“0x%x”, TAMARA.x.ax); /* vytiskne se 0x1234 */ }

Adresa struktury: 913E:0004 Hodnota y: 11 Adresa struktury: 913E:0008 struct TEST { int x; int y; } *p, *p1; p=(struct TEST*)calloc(1, sizeof(struct TEST)); p1=p; p->x=22; p->y=11; printf("\nAdresa struktury: %p", p); printf("\nHodnota y: %d", p->y); p++->y; p=p1; (--p)->y; p->y++; printf("\nHodnota y: %d", (p->y)++); (p->y)++; printf("\nHodnota y: %d", ++(p->y)); Adresa struktury: 913E:0004 Hodnota y: 11 Adresa struktury: 913E:0008 Hodnota y: 28531 Adresa struktury: 913E:0000 Hodnota y: -28387 Hodnota y: 12 Hodnota y: 15