Laboratorium nr 6

1/5

Język C

Instrukcja

laboratoryjna

Temat: Wskaźniki.

6

Przygotował: mgr inż . Maciej Lasota 1)

Wskaźniki.

Wskaźniki (zmienne wskaź nikowe) stanowią jedno z fundamentalnych pojęć języka C. Wskaźnik jest to zmienna przechowująca adres (znajdujący się w pamięci operacyjnej komputera) innej zmiennej, tablicy lub funkcji (zadeklarowanej w programie).

W języku C często wykorzystuje się wskaźniki, ze względu na to że jest to czasami jedyny sposób przedstawienia algorytmu obliczenia, częściowo zaś dlatego że ich użycie zwykle prowadzi do bardziej zwartego i efektywnego kodu. Deklaracja zmiennej wskaźnikowej polega na podaniu typu danych na jaki będzie wskaźnik wskazywał oraz podaniu gwiazdki „*”

przed nazwą zmiennej. Często stosuje się ujednolicone nazewnictwo zmiennych wskaźnikowych (np. dopisując do każdej zmiennej _ptr, _wsk itp.) w celu wyeliminowania późniejszych pomyłek.

Deklaracja zmiennej wskaźnikowej:

[typ danych] *[nazwa zmiennej wskaź nikowej];

Przykład:

int wiek;

//zwykle zmienne

char znak;

//zwykle zmienne

int *wiek_wsk;

//zmienne wskaznikowe

char *znak_wsk;

//zmienne wskaznikowe

Do zarządzania wskaźnikami wykorzystujemy dwa specjalne operatory. Pierwszym operatorem jest operator gwiazdki „*”, drugim zaś operator ampersand „&”.

•

„*” - operator „dereferencji” , czyli operator odwołania się danych wskazywanych przez dany wskaźnik.

•

„&” - operator pobrania adresu (zmiennej, struktury, tablicy itp.).

Laboratorium nr 6

2/5

Przykład:

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

int temp;

int *wskaznik;

temp = 100;

printf("Liczba w zmiennej TEMP: %d\n",temp); wskaznik = &temp;

// przypisujemy wskaznikowi

// adres zmiennej TEMP

*wskaznik = 200;

// pod adres wskaznika

// przypisujemy wartosc 200

printf("Liczba wskazywana przez

wskaznik: %d\n",*wskaznik);

return (0);

}

2)

Wskaźniki a tablice jednowymiarowe.

W języku C zacierają się różnice istniejące pomiędzy wskaźnikami i tablicami, w wielu przypadkach traktowane są tak samo. Wykonywana jest automatyczna konwersja między nimi. Elementy tablicy podczas tworzenia (uruchamiania programu) przypisywane są do kolejnych adresów w pamięci. Oznacza to że pierwszy element tablicy może znajdować się pod adresem 0xFF1000, natomiast kolejne elementy analogicznie pod adresami 0xFF1001, 0xFF1002, ... itd.

Taki sposób alokacji pamięci dla tablic w programach napisanych w języku C, pozwala na odnalezienie danego elementu tablicy za pomocą indeksów lub za pomocą wskaźników.

Przykład:

#include <stdio.h>

#include <stdlib.h>

int main()

{

int tab[4]={20,40,50,100};

int *wsk;

Laboratorium nr 6

3/5

wsk = &tab[0];

printf("Element pierwszy tablicy --> %d\n",*wsk); wsk = wsk + 1;

printf("Element drugi tablicy --> %d\n",*wsk); wsk++;

printf("Element trzeci tablicy --> %d\n",*wsk); wsk++;

*wsk = 200;

printf("Element czwarty tablicy --> %d\n",*wsk); return (0);

}

3)

Wskaźniki a tablice wielowymiarowe.

W języku C tablice wielowymiarowe, reprezentowane są jako tablice tablic (każdy element tablicy zawiera wskaźnik na tablicę). Zwiększenie liczby wymiarów tablicy zwiększa równocześnie poziom skomplikowania z punktu widzenia wskaźników.

Przykład:

#include <stdio.h>

#include <stdlib.h>

int main()

{

int macierz[4][4] = { {3,2,1,0}, {5,9,0,3},

{1,2,8,4}, {2,5,6,7} };

printf("macierz: \t%p\t\tmacierz+1:

\t%p\n",macierz,macierz+1);

printf("macierz[0]: \t%p\t\tmacierz[0]+1:

\t%p\n",macierz[0],macierz[0]+1);

printf("*macierz: \t%p\t\t*macierz+1:

\t%p \n",*macierz,*macierz+1);

printf("\n");

printf("macierz[0][0]: \t%d\n",macierz[0][0]); printf("macierz[1][1]: \t%d\n",macierz[1][1]); printf("macierz[2][3]: \t%d\n",macierz[2][3]); printf("\n");

Laboratorium nr 6

4/5

printf("*macierz[0]: \t%d\n",*macierz[0]); printf("*macierz[1]: \t%d\n",*macierz[1]); printf("*macierz[2]: \t%d\n",*macierz[2]); printf("\n");

printf("**macierz:

\t%d\n",*macierz[0]);

printf("*(*macierz+1): \t%d\n",*(*macierz+1)); printf("*(*macierz+2): \t%d\n",*(*macierz+2)); printf("\n");

printf("**macierz: \t\t%d\n",*macierz[0]); printf("*(*(macierz+1)+1): \t%d\n",*(*(macierz+1)+1)); printf("*(*(macierz+2)+3): \t%d\n",*(*(macierz+2)+3)); return (0);

}

4)

Wskaźniki a funkcje.

W języku C parametry do funkcji przekazywane są zawsze przez wartość (z wyją tkiem przekazywania tablic). Oznacza to, że w ciele funkcji operujemy jedynie na kopiach zmiennych. Czasami jednak w programie przydatna jest możliwość modyfikacji przekazywanych zmiennych.

Przekazując do funkcji zamiast zwykłych zmiennych wskaźniki do tych zmiennych, mamy możliwość modyfikacji oryginalnych wartości przechowywanych przez zmienne w ciele funkcji.

Przykład:

#include <stdio.h>

#include <stdlib.h>

void sum(int *k, int *l, int *s)

{

*s = (*k + *l);

}

int main()

{

int a,b;

int suma;

printf("Podaj liczbe a: ");

scanf("%d",&a);

printf("Podaj liczbe b: ");

scanf("%d",&b);

Laboratorium nr 6

5/5

sum(&a,&b,&suma);

printf("Suma: (%d + %d) = %d\n",a,b,suma); return (0);

}

5)

Wskaźniki a struktury danych.

W przypadku, gdy mamy zadeklarowany wskaźnik na strukturę danych, dostęp do poszczególnych składowych struktury odbywa się za pomocą tzw. notacji strzałkowej.

Notacja ta polega na podaniu wskaźnika do struktury, „->” (strzałki) oraz składowej do, której się odwołujemy

Przykład:

struct data

{

int dzien;

int miesiac;

int rok;

} data_urodzenia;

struct data *wsk;

wsk = &data_urodzenia;

scanf(”%d”,&wsk->dzien);

scanf(”%d”,&wsk->miesiac);

scanf(”%d”,&wsk->rok);

printf(”Data urodzenia: %d-%d-%d\n”

,wsk->dzien

,wsk->miesiac

,wsk->rok);