Jeżeli za dobrze nie czujecie się w adresach zmiennych ( zwyczajnych, nie wskaźników ), to proponuję najpierw zapoznać się z opisem umieszczonym tutaj: adresy zmiennych oraz ich rozmiary A wiodący tu przykład programu - wskazniki.c Często spotykam się ze stwierdzeniem "echh, nie czuję tych wskaźników". A tu okazuje się, że sprawa jest całkiem prosta, jeśli napisze się kilka programów, naprawdę prostych :) Głównie chodzi tu o wyświetlenie sobie zawartości wskaźników i adresów zmiennych, na które one wskazują :) Weźmy zmienną typu int oraz typu char * int a - zwykła zmienna char *wsk - dla wskaźnika Następnie przypiszmy wskaźnikowi adres tej zmiennej :) Spójrzcie na poniższy przykład int main ( void ) { int a = 2; /* deklaracja zmiennej */ char *wsk; /* wskaźnik */ /* przypisanie wskaźnikowi "wsk" adresu zmiennej "a" */ wsk = (char *)&a; printf("a: adres: %x, zawartosc: %d, dlugosc: %d \n", &a, a, sizeof(a)); printf("wsk: adres: %x, zawartosc: %x, dlugosc: %d \n", &wsk, wsk, sizeof(wsk)); return 0; } Jedna linijka, no może 2, wymagają szczególnego wyjaśnienia :) wsk jest zmienną wskaźnikową dzieki deklaracji char *wsk; Chodzi tu głównie o tę gwiazdkę * :) int a - zwyczajna zmienna typu int. Jeśli chcemy uzyskać zawartość zmiennej, to uzywamy samego "a" Natomiast, aby mieć adres zmiennej, to musimy napisać &a. To "wyłuska" jej adres :) W wyniku działania programu otrzymamy takie oto linijki: a: adres: bffffcd8, zawartosc: 2, dlugosc: 4 wsk: adres: bffffcd4, zawartosc: bffffcd8, dlugosc: 4 Jak widać, nagle może nas olśnić, czym naprawdę jest ten wskaźnik! :) W pierwszej linijce dowiadujemy się, że zmienna "a" znajduje się pod adresem bffffcd8, ma zawartość 2 oraz zajmuje 4 Bajty (jak to int). Kolejna linijka pokazuje wskaźnik. Znajduje się on pod adresem bffffcd4. Najważniejsza jednak, z punktu widzenia jego działania, jest zawartość :) Zauważcie, że jest w nim nie "2" ale adres pamięci - bffffcd8. Spójrzcie jeszcze raz na adres zmiennej "a". Czy to oby nie ten sam adres?.. :) Przyjęło się mówić, że wskaźniki operują nie na zmiennych, ale na ich adresach w pamięci. Teraz już wiecie czemu :) Ale jak to zrobić, mając sam wskaźnik, by dorwać się do zawartości zmiennej "a" wskazywanej przez sam wskaźnik "wsk"? :) Rozważmy takie coś: int main ( void ) { int a = 2; char *wsk; wsk = (char *)&a; printf("wsk: adres: %x, zawartosc: %x -> %d, dlugosc: %d \n", &wsk, wsk, *wsk, sizeof(wsk)); return 0; } Hmm.. co tu doszło.. Aby lepiej było widać różnicę, to napiszę to tak: printf("..........%d.........", ......, *wsk, ........); Wynik działania: wsk: adres: bffffcd4, zawartosc: bffffcd8 -> 2, dlugosc: 4 Aha! :) Mamy zawartość zmiennej "a". Jak to się mogło stać? :) Otóż pisząc *wsk nie dostajemy ani adresu wskaźnika ( bo od tego służy &wsk ), ani też jego zwyczajnej zawartości ( bo od tego z kolei jest samo wsk ). Otrzymujemy tu konkretną wartość, jaka została zapisana pod pamięcią, na którą wskazuje "wsk" :) Tak.. wiem. Zaczyna to być zakręcone :) Czasami myli się "*" z "&" i warto po prostu sprawdzić co to tak naprawdę oznacza, uzywając zwykłej funkcji printf() jak to było pokazane w tym opisie :) Wskaźniki wtedy nie są takie straszne, bo od razu widać jak na dłoni, co w nich siedzi :) Najczęściej będziecie musieli sprawdzić takie warianty: printf("%x\n", wsk); printf("%x\n", &wsk); printf("%d\n", *wsk); Ostatnia linijka może być różna, w zależności od tego, jakiego rodzaju była zmienna, na którą wskazywał wskaźnik :D Jeżeli to było np. int to dajemy %d, jeżeli string to %s. Dokładnie tak samo, jakbyśmy wyświetlali zawartości zwyczajnych zmiennych :)Na dziś to już koniec.. :) Jeżeli nie rozumiecie czegoś to proponuję zacząć naukę wskaźników od poznania zwykłych zmiennych, ich adresów oraz ilości Bajtów, jakie one zajmują. A wszystko to opisane było tutaj: adresy zmiennych oraz ich rozmiary Neutrinka www.kwant.info |