Ukazatele #1, struktury

Podobné dokumenty
Funkce, procedury, složitost

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

Mělká a hluboká kopie

Základy programování (IZP)

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

Ukazatele #2, dynamická alokace paměti

Základy programování (IZP)

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

Funkce, intuitivní chápání složitosti

Struktura programu v době běhu

Ukazatele, dynamická alokace

BI-PA1 Programování a Algoritmizace 1. Miroslav Baĺık, Ladislav Vagner a Josef Vogel. 7., 9. a 10. listopadu 2017

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) 28. prosince Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Základy programování (IZP)

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

BI-PA1 Programování a Algoritmizace 1. Miroslav Baĺık, Ladislav Vagner a Josef Vogel. 10., 12. a 13. října 2017

Abstraktní třídy, polymorfní struktury

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje

Více o konstruktorech a destruktorech

Úvod do programovacích jazyků (Java)

Funkce pokročilé možnosti. Úvod do programování 2 Tomáš Kühr

Strukturované typy a ukazatele. Úvod do programování 1 Tomáš Kühr

Pole a Funkce. Úvod do programování 1 Tomáš Kühr

Základy C++ I. Jan Hnilica Počítačové modelování 18

8 Třídy, objekty, metody, předávání argumentů metod

Jazyk C++, některá rozšíření oproti C

Dekompozice problému, rekurze

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Příkazy if, while, do-while, for, switch

PB071 Programování v jazyce C Jaro 2013

IUJCE 07/08 Přednáška č. 1

Programování v jazyce C a C++

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Stromy, soubory. BI-PA1 Programování a Algoritmizace 1. Ladislav Vagner, Josef Vogel

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Správa paměti. doc. Ing. Miroslav Beneš, Ph.D. katedra informatiky FEI VŠB-TUO A-1007 /

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

Algoritmizace a programování

Odvozené a strukturované typy dat

2 Datové typy v jazyce C

Základní datové typy, proměnné - deklarujeme předem - C je case sensitive rozlišuje malá a velká písmena v názvech proměnných a funkcí

Reprezentace dat v informačních systémech. Jaroslav Šmarda

Pointery II. Jan Hnilica Počítačové modelování 17

Ukazatel (Pointer) jako datový typ - proměnné jsou umístěny v paměti na určitém místě (adrese) a zabírají určitý prostor (počet bytů), který je daný

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Programování v C++, 2. cvičení

Abstraktní datové typy, moduly

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

Paměť počítače. alg2 1

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

Rekurzivní algoritmy

Programování v C++ 1, 1. cvičení

PROGRAMOVÁNÍ V JAZYCE C V PŘÍKLADECH 11 Dynamické datové struktury 11.1 Spojové struktury Příklad PROG_

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Spojová implementace lineárních datových struktur

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Lineární spojový seznam (úvod do dynamických datových struktur)

7. Datové typy v Javě

přetížení operátorů (o)

Dynamické datové struktury III.

C++ přetěžování funkcí a operátorů. Jan Hnilica Počítačové modelování 19

Jazyk C# a platforma.net

přetížení operátorů (o)

Základy programování (IZP)

Programování v jazyce C a C++

Př. další použití pointerů

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Výrazy, operace, příkazy

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

Úvod do programování - Java. Cvičení č.4

Bitové operátory a bitová pole. Úvod do programování 2 Tomáš Kühr

Třídy a struktury v C++

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

6. lekce Úvod do jazyka C knihovny datové typy, definice proměnných základní struktura programu a jeho editace Miroslav Jílek

Operační systémy. Cvičení 3: Programování v C pod Unixem

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

IUJCE 07/08 Přednáška č. 6

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

DTP Základy programování Úvod do předmětu

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Operační systémy. Cvičení 4: Programování v C pod Unixem

Ukazatele a pole. Chceme-li vyplnit celé pole nulami, použijeme prázdný inicializátor: 207 Čárka na konci seznamu inicializátorů

Dynamická alokace paměti

Opakování programování

int ii char [16] double dd název adresa / proměnná N = nevyužito xxx xxx xxx N xxx xxx N xxx N

Např.: // v hlavičkovém souboru nebo na začátku // programu (pod include): typedef struct { char jmeno[20]; char prijmeni[20]; int rok_nar; } CLOVEK;

PODOBÁ SE JAZYKU C S NĚKTERÝMI OMEZENÍMI GLOBÁLNÍ PROMĚNNÉ. NSWI162: Sémantika programů 2

Základy programování. Úloha: Eratosthenovo síto. Autor: Josef Hrabal Číslo: HRA0031 Datum: Předmět: ZAP

Paralelní architektury se sdílenou pamětí typu NUMA. NUMA architektury

Abstraktní datové typy

Obsah přednášky. programovacího jazyka. Motivace. Princip denotační sémantiky Sémantické funkce Výrazy Příkazy Vstup a výstup Kontinuace Program

Řídicí struktury. alg3 1

Transkript:

Ukazatele #1, struktury BI-PA1 Programování a Algoritmizace 1 Miroslav Baĺık, Ladislav Vagner a Josef Vogel Katedra teoretické informatiky a Katedra softwarového inženýrství Fakulta informačních technologíı České vysoké učení technické v Praze xvagner@fit.cvut.cz, vogeljos@fit.cvut.cz 14., 23. a 24. listopadu 2017

Přehled Datové typy ukazatel. Ukazatele reference, dereference. Struktura jako datový typ. Pamět ová reprezentace struktury. Pole struktur, ukazatele na struktury. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 2/35

Ukazatele motivace Chceme pracovat s daty uvnitř nějaké funkce. Data si do funkce můžeme předat zkopírováním: void foo ( int x )... int data =...; foo ( data ); funkce má k dispozici vlastní proměnnou x, tato proměnná obsahuje kopii hodnoty z proměnné data, proměnná data se jednorázově zkopíruje do x, od tohoto okamžiku nemají proměnné nic společného, funkce foo může hodnotu proměnné x zničit (přepsat), tím nezmění data. Kopírování proměnné nemusí být vždy výhodné. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 3/35

Ukazatele motivace Kdy je kopírování nevýhodné: kopírování může trvat dlouho, pokud je proměnná velká. Kopírování proměnné typu int je velmi rychlé, režie kopírování by se uplatnila pro proměnné od velikosti řádově stovek bajtů, změny v proměnné x uvnitř foo nejsou vidět ven, toto požadujeme např. u výstupních parametrů. Místo kopie hodnoty proměnné bychom mohli funkci předat informaci o umístění proměnné, se kterou má pracovat. Informace o umístění proměnné je její adresa v paměti. void foo ( int * x )... int data =...; foo ( &data ); M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 4/35

Ukazatele Ukazatele abstrakce adres ve vyšších programovacích jazycích. Hodnota ukazatele na typ T reprezentuje adresu v paměti, kde je hodnota typu T uložena. Deklarace ukazatele: T * ptr Proměnná ptr reprezentuje adresu. Stejně jako u jiných (lokálních) proměnných, je počáteční hodnota nedefinována. Proměnná může být inicializována adresou: T x; /* proměnná typu T, kdekoli deklarovaná */... T * p = & x; /* alternativně mimo deklaraci: */ p = & x; Unární prefixový operátor & se nazývá reference (odkaz). Výsledkem operace &x je ukazatel (adresa) proměnné x. Ukazatel je datového typu T* ukazatel na hodnoty typu T. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 5/35

Ukazatele reference Vlastní adresa je celé číslo udávající pozici proměnné v paměti (počítáno v bajtech od počátku pamět ového prostoru). Zjednodušeně pokud tuto kombinaci bitů pošle CPU na adresní sběrnici, pamět ový čip zpřístupní odpovídající obsah. Skutečné hodnoty adres jsou jen málokdy důležité: adresy proměnných jsou přiděleny kompilátorem, adresy proměnných se mohou lišit, závisí na kompilátoru, OS, nebo na okamžitém využití paměti. Je obvyklé označovat adresy šipkou vedoucí od ukazatele k referencované proměnné. int x = 10, *iptr = &x; char c = a, *cptr; cptr = &c; x iptr c cptr 10 'a' M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 6/35

Ukazatele dereference Pro přístup k proměnné, jež je referencována ukazatelem, musí být použit operátor dereference *. Když ptr je ukazatel typu T*, pak výraz *ptr označuje hodnotu referencovanou tímto ukazatelem ptr. int x, *iptr = &x; char c, *cptr; cptr = &c; *iptr = 20; *cptr = Z ; x iptr c cptr 20 'Z' M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 7/35

Ukazatele kompatibilita Ukazatele stejného typu je možno přiřazovat: int x, *p1 = &x, *p2; p2 = p1; /* p1 a p2 nyní referencují proměnnou - x */ *p2 = 10; /* x má nyní hodnotu 10 */ Když přiřazujeme adresy různých typů (např.. T1* a T2*), kompilátor hlásí varovnou zprávu, ale kód je vytvořen. Výsledek dereferencování takové adresy je podivný (špatná interpretace hodnoty, data přepsána,... ). M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 8/35

Ukazatele kompatibilita int x, *iptr; char c, *cptr; iptr = &c; /*!!! */ cptr = &x; /*!!! */ *iptr = 0; /* Čtyři bajty od adresy proměnné c jsou naplněny nulami. Možná je nějaká proměnná přepsána (třeba zrovna adresa v cptr). */ *cptr = 0; /* První bajt proměnné x je vynulován. Zbylé tři bajty jsou nezměněny. Hodnota proměnné x nemusí být 0. */ M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 9/35

Ukazatele poznámka k pořadí bajtů v paměti Jak je uložena např. hodnota x = 305419896 = 0x12345678? Hodnota (32 bitů) bude zaujímat 4 bajty paměti: little-endian (Intel): 0x78 0x56 0x34 0x12 big-endian (Motorola, SPARC): 0x12 0x34 0x56 0x78 bi-endian (can switch in boot time): ARM, PowerPC, MIPS, IA64 Efekt posledního příkladu (*cptr=0;) velmi závisí na architektuře procesoru. Vynulován bude nejnižší nebo nejvyšší bajt proměnné x. Tedy hodnota se změní bud na 0x00345678 = 3430008, nebo na 0x12345600 = 305419776. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 10/35

Ukazatele ukazatel NULL Ukazatel NULL speciální hodnota adresy, která nic nereferencuje. Hodnota NULL ukazatele je používána pro signalizaci speciálních případů (např. operace selhala). V jazyce C je hodnota NULL definována: #define NULL ((void*)0) Pokus o dereferenci ukazatele NULL vede k pádu programu: int main(void) { int *p = NULL; *p = 10; /* zde spadne */ printf ( "Hello world!\n" ); return 0; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 11/35

Ukazatele (de)motivace Za obrázek děkujeme Randallu Munroe, XKCD comics #138 (xkcd.com). M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 12/35

Ukazatele (de)motivace Za obrázek děkujeme Randallu Munroe, XKCD comics #138 (xkcd.com). Pointers will be back next week! M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 12/35

Struktury motivace Problém: přečíst jméno studenta, příjmení studenta a jeho průměrný prospěch, vstupní data jsou na std. vstupu, vypsat studenta s nejlepším průměrem. Příklad: John Smith 2.45 George Peterson 1.32 Peter O Brien 1.93 Michael Corleone 2.21 Výsledek: George Peterson 1.32 M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 13/35

Struktury motivace Nástin řešení: inicializace proměnné(ých) nejlepší_student while ( další student přečten ) porovnání do ted nejlepšího průměru s průměrem právě přečteného if je lepší then uložení jména, příjmení a průměru do nejlepší_student výpis nejlepšího_studenta M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 14/35

Struktury motivace #define NAME_MAX 32 int main ( void ) { char curname[name_max], cursurname[name_max]; char bestname[name_max], bestsurname[name_max]; double bestavg = 5, curavg; while ( scanf ( "%31s%31s%lf", curname, cursurname, &curavg ) == 3 ) { printf ( "%s %s: %f\n", curname, cursurname, curavg ); if ( curavg < bestavg ) { /* ok, přiřadit */ bestavg = curavg; strncpy ( bestname, curname, sizeof(bestname) ); strncpy ( bestsurname, cursurname, sizeof(bestsurname) ); printf ( "Nejlepsi prumer:\n" ); printf ( "%s %s: %f\n", bestname, bestsurname, bestavg ); return 0; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 15/35

Struktury Nevýhody řešení: příliš mnoho proměnných, související proměnné jsou jen slabě propojeny (podobné pojmenování, případně stejný index v poĺıch), když přidáme novou informaci (třeba datum narození), bude třeba program modifikovat na mnoha místech. Lepší řešení použití struktury. Struktura je složený datový typ, který spojuje související informace (proměnné) do jedné větší jednotky. Struktury lze přirovnat k funkcím: funkce spojují související akce (výpočty) do jedné větší jednotky, struktury spojují související data (proměnné) do jedné větší jednotky. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 16/35

Struktury #define NAME_MAX 32 struct TStudent { /* jméno datového typu */ char name[name_max]; /* složky (položky struktury) */ char surname[name_max]; double avg; ; int main ( void ) { struct TStudent cur, best; best. avg = 5; /* přístup ke složce */... M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 17/35

Struktury struct TStudent {... ; int main ( void ) { struct TStudent cur, best; best.avg = 5; while ( scanf ( "%31s%31s%lf", cur.name, cur.surname, &cur.avg ) == 3 ) { printf ( "%s %s: %f\n", cur.name, cur.surname, cur.avg ); if ( cur.avg < best.avg ) best = cur; /* ok, přiřadit */ printf ( "Nejlepsi prumer:\n" ); printf ( "%s %s: %f\n", best.name, best.surname, best.avg ); return 0; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 18/35

Struktury Jméno typu struct TStudent je poněkud zdlouhavé. Je možné používat kratší jméno, když definici struktury modifikujeme: typedef struct TStudent { /* typedef deklaruje */ char name[name_max]; /* nové jméno typu */ char surname[name_max]; double avg; TSTUDENT; /* TSTUDENT je nové, jednoduché jméno typu struct TStudent */ int main ( void ) { TSTUDENT cur, best; /* jméno typu */... /* bez klíčového slova struct */ M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 19/35

Struktury deklarace detailněji struct TStudent { char name[name_max]; char surname[name_max]; double avg; foo; /* struct TStudent je jméno datového typu: */ struct TStudent a; /* a je proměnná */ /* foo je proměnná typu struct TStudent: */ printf ( "%s\n", foo. name ); M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 20/35

Struktury deklarace detailněji typedef struct TStudent { char name[name_max]; char surname[name_max]; double avg; TSTUDENT; /* struct TStudent je jméno datového typu: */ struct TStudent a; /* a je proměnná */ /* TSTUDENT je jméno datového typu: */ TSTUDENT b; /* b je proměnná */ a = b; /* stejný datový typ, tedy lze přiřazovat */ M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 21/35

Struktury deklarace detailněji typedef struct { char name[name_max]; char surname[name_max]; double avg; TSTUDENT; typedef struct { char name[name_max]; char surname[name_max]; double avg; XSTUDENT; TSTUDENT a; XSTUDENT b; a = b; /* nelze přiřadit, odlišný datový typ */ M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 22/35

Struktury reprezentace v paměti #define NAME_MAX 32 typedef struct TStudent { char name[name_max]; char surname[name_max]; double avg; TSTUDENT; TSTUDENT student = {"John", "Smith", 1.35 ; /* init */ +0 'J' 'o' 'h' 'n' '\0'... +32 'S' 'm' 'i' 't' 'h' '\0'... +64 1.35 (as a double) +72 size of the structure M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 23/35

Struktury reprezentace v paměti #define NAME_MAX 32 typedef struct TStudent { char name[name_max]; char surname[name_max]; double avg; TSTUDENT; int main ( void ) { TSTUDENT x; printf ( "name: %d\n", (int)((char*)&x.name - (char*)&x) ); printf ( "surname: %d\n", (int)((char*)&x.surname - (char*)&x) ); printf ( "avg: %d\n", (int)((char*)&x.avg - (char*)&x) ); printf ( "sizeof: %d\n", (int)sizeof ( x ) ); return 0; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 24/35

Struktury reprezentace v paměti Při spuštění program vypíše očekávané hodnoty: 0, 32, 64, a 72. Co se stane, když deklaraci modifikujeme? #define NAME_MAX 33 Modifikovaný program nevypíše: 0, 33, 66, 74, ale místo toho 0, 33, 72, 80. Složka avg má délku 8 bajtů. Nejrychlejší přístup k této položce vyžaduje, aby počáteční adresa byla dělitelná 8. Když není předchozí podmínka splněna, procesor čte položku více cykly sběrnice (Intel, AMD) nebo odmítne položku přečíst vůbec a dojde ke pádu programu (SPARC, MIPS). M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 25/35

Struktury reprezentace v paměti Kompilátor provádí tedy tzv. zarovnání (aligning): položky struktur nebo proměnné o velikosti 2 k bajtů jsou alokovány na adresách začínajících na násobku 2 k, v našem příkladu kompilátor vložil 6 bajtů navíc mezi položky surname a avg, když je program napsán korektně, tak tyto bajty nejsou vůbec používány, kvůli rychlému přístupu je položka avg je zarovnána. Zarovnání proměnných je významně platformně závislé. Přenositelná aplikace nesmí záviset na platformě specifických velikostech/zarovnání proměnných. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 26/35

Struktury a pole Příklad: Program čte studenty, ukládá je do paměti, řadí je podle průměrného prospěchu a pak je vypíše. Uvedeme funkce, které vedou na lépe přehledné a čitelné řešení: void printstudent ( TSTUDENT s ); int readstudent ( TSTUDENT * ps ); void sortstudents ( TSTUDENT a[], int n ); M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 27/35

Struktury a pole int main( void ) { TSTUDENT students[max]; int cnt = 0, i; while ( cnt < MAX && readstudent ( &students[cnt] ) ) cnt ++; sortstudents ( students, cnt ); for ( i = 0; i < cnt; i ++ ) printstudent ( students[i] ); return 0; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 28/35

Struktury a pole Seřazení pole algoritmem select sort: V poli nalezneme nejmenší prvek a prohodíme jej s prvkem na indexu 0. Ve zbytku pole (od indexu 1) nalezneme nejmenší prvek a prohodíme jej s prvkem na indexu 1. To samé se zbytku počínaje indexy 2, 3,.... Výsledkem je seřazené pole. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 29/35

Struktury a pole void sortstudents ( TSTUDENT a[], int n ) { int i, j, imin; for ( i = 0; i < n - 1; i ++ ) { imin = i; /* umístění nejmenšího prvku */ for ( j = i + 1; j < n; j ++ ) if ( a[j].avg < a[imin].avg ) imin = j; /* na pozici j je menší */ if ( imin!= i ) { TSTUDENT tmp = a[imin]; /* prohození obsahu */ a[imin] = a[i]; /* všech složek zároveň */ a[i] = tmp M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 30/35

Struktury a pole void printstudent ( TSTUDENT s ) { printf ( "%s %s %f\n", s.name, s.surname, s.avg ); int readstudent ( TSTUDENT * ps ) { /* ps je výstupní parametr, předáme jej jako ukazatel */ TSTUDENT s; if ( scanf ( "%31s%31s%lf", s.name, s.surname, &s.avg )!= 3 ) return 0; *ps = s; return 1; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 31/35

Struktury a pole void printstudent ( TSTUDENT s ) { printf ( "%s %s %f\n", s.name, s.surname, s.avg ); int readstudent ( TSTUDENT * ps ) { /* ps je výstupní parametr, předáme jej jako ukazatel */ TSTUDENT s; if ( scanf ( "%31s%31s%lf", s.name, s.surname, &s.avg )!= 3 ) return 0; *ps = s; return 1; Struktura TSTUDENT je dost velká. Vyplatí se její kopírování při každém volání printstudent? M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 31/35

Struktury a pole void printstudent ( TSTUDENT s ) { printf ( "%s %s %f\n", s.name, s.surname, s.avg ); int readstudent ( TSTUDENT * ps ) { /* ps je výstupní parametr, předáme jej jako ukazatel */ TSTUDENT s; if ( scanf ( "%31s%31s%lf", s.name, s.surname, &s.avg )!= 3 ) return 0; *ps = s; return 1; Struktura TSTUDENT je dost velká. Vyplatí se její kopírování při každém volání printstudent? Je potřeba při načítání zapsat data do lokální proměnné a pak je zkopírovat do parametru? Nešlo by to přímo? M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 31/35

Struktury a pole void printstudent ( TSTUDENT * s ) { /* s je dost velký (~100 B) vstupní parametr, který funkce * pouze čte. Proto jej z výkonnostních důvodů předáme * odkazem (jako ukazatel). Volající použije: * printstudent( &students[i] ); */ printf ( "%s %s %f\n", (*s).name, (*s).surname, (*s).avg ); int readstudent ( TSTUDENT * s ) { /* s je výstupní parametr, předáme jej jako ukazatel */ if ( scanf ( "%31s%31s%lf", (*s).name, (*s).surname, &(*s).avg )!= 3 ) return 0; return 1; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 32/35

Struktury a pole void printstudent ( TSTUDENT * s ) { /* s je dost velký (~100 B) vstupní parametr, který funkce * pouze čte. Proto jej z výkonnostních důvodů předáme * odkazem (jako ukazatel). Volající použije: * printstudent( &students[i] ); */ printf ( "%s %s %f\n", (*s).name, (*s).surname, (*s).avg ); int readstudent ( TSTUDENT * s ) { /* s je výstupní parametr, předáme jej jako ukazatel */ if ( scanf ( "%31s%31s%lf", (*s).name, (*s).surname, &(*s).avg )!= 3 ) return 0; return 1; Zápis (*s).name je zdlouhavý a nepřehledný. Lze jej nahradit operátorem ->. M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 32/35

Ukazatele a struktury void printstudent ( TSTUDENT * s ) { /* s je dost velký (~100 B) vstupní parametr, který funkce * pouze čte. Proto jej z výkonnostních důvodů předáme * odkazem (jako ukazatel). Volající použije: * printstudent( &students[i] ); */ printf ( "%s %s %f\n", s->name, s->surname, s->avg ); int readstudent ( TSTUDENT * s ) { /* s je výstupní parametr, předáme jej jako ukazatel */ if ( scanf ( "%31s%31s%lf", s->name, s->surname, &s->avg )!= 3 ) return 0; return 1; M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 33/35

Ukazatele a struktury Při práci s ukazateli na strukturu často potřebujeme ukazatel dereferencovat a následně zpřístupnit složku struktury. Např.: TSTUDENT *p;... (*p).name... Tuto operaci lze nahradit jediným operátorem šipka. Kód se lépe píše a je přehlednější: TSTUDENT *p;... p->name... Následující zápisy jsou rovnocenné: TSTUDENT *p; TSTUDENT s;... s. name <=> (&s) -> name p -> name <=> (*p). name M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 34/35

Otázky a odpovědi Otázky... M. Baĺık, L. Vagner a J. Vogel, ČVUT FIT Ukazatele, BI-PA1 35/35