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 5­elementowe 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 (bit­field) 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ć &