Struktury - Politechnika Śląska
Transkrypt
Struktury - Politechnika Śląska
Programowanie komputerów Jacek Lach Zakład Oprogramowania Instytut Informatyki Politechnika Śląska Plan • Nazywanie typów Jacek Lach. Programowanie komputerów • Struktury • Unie • Pola bitowe Nazywanie typów Jacek Lach. Programowanie komputerów • C pozwala nazwać tworzone przez programistę typy; stosuje się do tego celu typedef • typedef nie deklaruje obiektów; definiuje identyfikator nazywający typ; taki identyfikator nazywany jest nazwą typedef • typedef nie wprowadza nowych typów, tylko synonimy dla typów, które mogą zostać też opisane w inny sposób • Zapis bez słowa typedef definiuje zmienną Przykłady • typedef long Blockno, *Blockptr; Blockptr p1; Jacek Lach. Programowanie komputerów • typedef unsigned char uchar • typedef unsigned short __u16; typedef __signed__ int __s32; typedef unsigned int __u32; typedef unsigned long long __u64; typedef __u8 uint8_t; typedef __u16 uint16_t; typedef __u32 uint32_t; Jacek Lach. Programowanie komputerów Skomplikowane deklaracje • Porównajmy int *f(); /* f: funkcja zwracająca wskaźnik na int */ i int (*pf)(); /* pf: wskaźnik na funkcję zwracającą int */ • Nawiasy są niezbędne w drugiej deklaracji Skomplikowane deklaracje • char **argv argv: wskaźnik na wskaźnik na char • int (*daytab)[13] daytab: wskaźnik na tablicę 13 elementów typu int Jacek Lach. Programowanie komputerów • int *daytab[13] daytab: tablica 13 wskaźników na int • void *comp() comp: funkcja zwracająca wskaźnik na void • void (*comp)() comp: wskaźnik na funkcję zwracajacą void • char (*(*x())[])() x: funkcja zwracajaca wskaźnik na tablicę wskaźników na funkcje zwracające char • char (*(*x[3])())[5] x: tablica 3 wskaźników na funkcje zwracające wskaźniki na 5elementowe tablice elementów typu char Jacek Lach. Programowanie komputerów Skomplikowane deklaracje • Dla skomplikowanych deklaracji, wygodniej użyć kilku typedef zamiast pojedynczej deklaracji; np. zamiast: char *(*(*a[N])())(); (tablica N wskaźników na funkcje zwracające wskaźniki na funkcje zwracające wskaźniki na char) można użyć: typedef char *pc; /* wskaźnik na char */ typedef pc fpc(); /* funkcja zwr. wskaźnik na char */ typedef fpc *pfpc; /* wskaźnik na w/w */ typedef pfpc fpfpc(); /* funkcja zwracająca... */ typedef fpfpc *pfpfpc; /* wskaźnik na... */ pfpfpc a[N]; /* tablica... */ Struktury Jacek Lach. Programowanie komputerów • Struktura jest obiektem zawierającym ciąg nazwanych składowych niekoniecznie tego samego typu • Słowo struct wprowadza deklarację struktury, która jest listą deklaracji ujętą w nawiasy klamrowe • Po słowie struct może wystąpić opcjonalna nazwa (etykietka struktury structure tag) • Nazwa ta opisuje ten rodzaj struktury i może zostać użyta potem jako skrót dla części deklaracji występującej w nawiasach klamrowych Struktury Jacek Lach. Programowanie komputerów • Przykład: struct point { int x; int y; }; • Dostęp: nazwa_struktury.składowa Jacek Lach. Programowanie komputerów Struktury • Przykład: struct point { /* opcjonalna nazwa */ int x; int y; /* składowe */ } k; /* opcjonalne definicje zmiennych */ struct point v, w; v.x = 7; v.y = 9; w = v; Struktury Jacek Lach. Programowanie komputerów • Strukturę można inicjować podając listę wartości początkowych jej składowych: struct point pt = {300, 215}; • Automatyczną strukturę można też inicjować za pomocą przypisania lub wywołania funkcji Struktury • Dozwolone operacje: • Przepisanie innej struktury w całości Jacek Lach. Programowanie komputerów • Skopiowanie w całości na inną strukturę • Pobranie adresu za pomocą operatora & • Odwołania do składowych • Struktur NIE można porównywać • Jeżeli p jest wskaźnikiem do struktury, to p>składowa_struktury jest odwołaniem do składowej, równoważne (*p).składowa_struktury Struktury Jacek Lach. Programowanie komputerów • Operatory strukturowe: . i > wiążą najsilniej swoje argumenty. • Dla deklaracji struct { int len; char *str; } *p; • ++p>len Zwiększa zmienną len • (++p)>len Zwiększa p przed odwołaniem do len • (p++)>len Zwiększa p po odwołaniu do len • *p>str Udostępnia to, na co wskazuje str Nazywanie typów strukturalnych typedef struct { ...działa jak: struct compl { Jacek Lach. Programowanie komputerów float re, im; } tcompl; float re, im; }; tcompl a, b, c; struct compl a, b, c; a.re = 10.5; a.re = 10.5; a.im = 36.6; ... b = c = a; albo: struct { float re, im; } a, b, c; Do czego służą nazwy struktur? struct { Jacek Lach. Programowanie komputerów float re, im; struct compl { float re, im; } a, b; } a, b; struct { struct compl c; float re, im; ... } c; c = a; a.re = 10.5; struct { a.im = 36.6; float re, im; } a, b, c; c = a; ZAKAZANE OK Struktury mogą być zwracane przez funkcje typedef struct { float re, im; Jacek Lach. Programowanie komputerów } cplx; cplx mult(cplx c, float x) { c.im *= x; c.re *= x; return c; } Struktury mogą być zagnieżdżane typedef struct { char name[50]; Jacek Lach. Programowanie komputerów struct { int year, month, day; } birthdate; } tperson; tperson p1; strcpy(p1.name,"Jan Kowalski"); p1.birthdate.year = 1945; p1.birthdate.month = 1; p1.birthdate.day = 17; Tablice struktur typedef struct { double re,im; Jacek Lach. Programowanie komputerów } tcplx; void test() { int i; tcplx tab[50]; for (i=0;i<50;i++) tab[i].re = tab[i].im = 0.0; } Unie Jacek Lach. Programowanie komputerów • Unia jest zmienną przechowującą w jednym miejscu pamięci wartości różnych typów (w różnym czasie) • Kompilator dba o rozmiar unii i rozmieszczenie danych • Składnia: podobna do struktur Jacek Lach. Programowanie komputerów Unie union u_tag { int ival; float fval; char *sval; } u; • Zmienna u będzie wystarczająco duża, aby przechować największy z typów • Dokładny rozmiar jest zależny od implementacji • Zmienne tych typów mogą być stosowane w przypisaniach • Odczytywany typ powinien być taki, jak ostatnio zapisany • Programista jest odpowiedzialny za przechowywanie informacji, który z typów jest aktualnie stosowany • W razie próby odczytu innego typu niż zapisany, wyniki są zależne od implementacji Unie Jacek Lach. Programowanie komputerów • Unie mogą wystąpić w strukturach i odwrotnie • Notacja jest analogiczna jak dla zagnieżdżonych struktur Jacek Lach. Programowanie komputerów Unie struct { char *name; int flags; int utype; union { int ival; float fval; char *sval; } u; } symtab[NSYM]; Dostęp do składowej ival: symtab[i].u.ival Pierwszy znak łańcucha sval: *symtab[i].u.sval symtab[i].u.sval[0] Unie Jacek Lach. Programowanie komputerów • Dozwolone operacje: • • • • Przepisanie innej unii w całości Skopiowanie w całości na inną unię Pobranie adresu za pomocą operatora & Odwołania do składowych • Inicjalizacja: wartością o typie jej pierwszej składowej • Dostęp: nazwa_unii.składowa_unii lub jeżeli p jest wskaźnikiem do unii, to p->składowa_unii jest odwołaniem do składowej, równoważne (*p).składowa_unii Pola bitowe • Przydatne może być zapisanie kilku liczb w jednym słowie maszynowym Jacek Lach. Programowanie komputerów • Często stosowane: jednobitowe flagi • Inny przykład: dostęp do urządzeń zewnętrznych wymaga dostępu do fragmentów słowa maszynowego • Zwykle stosowane rozwiązanie: maski, przesuwanie, maski... • Alternatywa w C: pola bitowe • Pole bitowe (bitfield) jest zbiorem sąsiadujących ze sobą bitów w obrębie jednej jednostki pamięci nazywanej „słowem” Pola bitowe Jacek Lach. Programowanie komputerów • Składnia: podobna do struktur • Przykład: struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags; • Definiujemy zmienną flags zawierającą trzy pola jednobitowe. Pola bitowe Jacek Lach. Programowanie komputerów • Liczba po dwukropku definiuje liczbę bitów w polu bitowym. Pola są typu unsigned int aby zapewnić nieujemne wartości. • Do poszczególnych pól odwołujemy się jak do składowych struktury: flags.is_keyword, flags.is_extern, itd. • Pola bitowe zachowują się jak małe liczby całkowite i mogą być stosowane w wyrażeniach tak, jak inne liczby całkowite Pola bitowe Jacek Lach. Programowanie komputerów • Prawie wszystko zależy tu od implementacji np. dopuszczalność przekroczenia granicy słowa • Pola nie muszą być nazywane; sam dwukropek z długością wprowadza anonimowe pole, np. do wypełnienia miejsca • Specjalna wartość szerokości 0 może być stosowana do wymuszenia przeniesienia granicy pola do granicy następnego słowa • Miejsce dla pól przydzielane od lewej do prawej lub odwrotnie Pola bitowe • Ostrożnie z dostępem do danych binarnych w ten sposób Jacek Lach. Programowanie komputerów • Programy opierające się na tym nie są przenośne • Pola mogą być definiowane tylko jako int (signed lub unsigned) • Nie są tablicami, nie mają adresów, nie można do nich stosować &