Język C

advertisement
Laboratorium nr 6
Instrukcja
laboratoryjna
6
1)
1/5
Język C
Temat: Wskaźniki.
Przygotował: mgr inż. Maciej Lasota
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;
char znak;
//zwykle zmienne
//zwykle zmienne
int *wiek_wsk;
char *znak_wsk;
//zmienne wskaznikowe
//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);
Download