wskaźniki na zmienne



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