6 STRUKTURY_______
Ta funkcja zakłada, że prostokąt jest reprezentowany w standardowej postaci (kanonicznej), gdzie współrzędne punktu p1 są mniejsze niż współrzędne punktu p2. Następująca funkcja sprowadza prostokąt do postaci kanonicznej:
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
I* canonrect: znormalizuj współrzędne prostokąta do postaci kanonicznej */ struct rect canonrect(struct rect r)
struct rect temp;
temp.pfl.x = min(r.pt1.x, r.pt2.x); temp.ptl.y = min(r.pt1.y, r.pt2.y); temp.pt2.x = max(r.pfl.x, r.pt2.x); temp.pt2.y = max(r.pt1.y, r.pt2.y); return temp;
Jeśli funkcji trzeba przekazać dużą strukturę, to przekazywanie wskaźnika jest zwykle bardziej skuteczne niż kopiowanie zawartości całej struktury. Wskaźniki do struktur są takimi samymi wskaźnikami, jak do zwykłych zmiennych. Deklaracja
struct point *pp;
mówi, że pp jest wskaźnikiem do struktury typu struct point. Jeśli pp wskazuje na strukturę typu point, to *pp jest taką strukturą, a (*pp).x oraz (*pp).y są jej składowymi. Posługując się wskaźnikiem pp, możemy na przykład napisać
struct point origin, *pp;
pp = &origin;
printf(”punkt początkowy (%d,%d)\n”, (*pp).x, (*pp).y);
W wyrażeniu (*pp).x nawiasy są konieczne, gdyż operator składowej struktury . ma priorytet wyższy niż operator adresowania pośredniego *. Wyrażenie *pp.x znaczy więc tyle, co *(pp.x), a to wyrażenie jest tutaj błędne, ponieważ X nie jest wskaźnikiem.
Wskaźników do struktur używa się tak często, że w języku występuje specjalna notacja umożliwiająca skrócony zapis. Jeśli p jest wskaźnikiem do struktury, to
p ->sktado wa-struktury
6.2 STRUKTURY I FUNKCJE________
—i-powej^ed-by
z możemy więc
jest odwołaniem do konkretnej składowej tej struktury. (Operator ->
^ znaku minus i bezpośrednio po nim następującego znaku >.) Tera napisać
printf(”punkt początkowy (%d,%d)\n”, pp->x, pp—>y);
Oba operatory . i -> są lewostronnie łączne, toteż na przykład po takiej definicji struct rect r, *rp = &r;
następujące cztery wyrażenia są równoważne:
r.ptl .x rp->pt1 .x (r.ptl ).x (rp->pt1).x
Operatory strukturowe . i ->, wraz z nawiasami okrągłymi () wywołania funkcji i kwadratowymi [] indeksowania tablicy, znajdują się na szczycie hierarchii priorytetów, a więc najsilniej wiążą swoje argumenty. Dla przykładu po deklaracji
struct { int len; char *str;
}*p;
wyrażenie
++p->len
zwiększa zmienną len, a nie wskaźnik p, ponieważ stawiając nawiasy zgodnie z priorytetem operatorów otrzymamy ++(p->len). Stosując nawiasy można zmieniać przywiązanie argumentów: wyrażenie (-H-p)->len zwiększa p przed odwołaniem do len, a wyrażenie (p++)->len zwiększa p po takim odwołaniu. (W tym ostatnim wyrażeniu nawiasy są zbędne.)
Na tej samej zasadzie wyrażenie *p->str udostępnia to coś, na co wskazuje str, wyrażenie *p->str++ zwiększa str po udostępnieniu obiektu wskazywanego przez str 'żak samo, jak konstrukcja *s++), wyrażenie (*p->str)++ zwiększa to coś, na co Okazuje str, a wyrażenie *p+-t-->str zwiększa p po udostępnieniu obiektu wskazywanego przez str.
179