Podstawy programowania
This presentation is the property of its rightful owner.
Sponsored Links
1 / 28

Wyk ł ad 1 : Wskaźniki PowerPoint PPT Presentation


  • 88 Views
  • Uploaded on
  • Presentation posted in: General

Podstawy programowania Programowanie w C. Wyk ł ad 1 : Wskaźniki. Dr inż. Zdzisława Rowińska III p. KIS, pokój 314, [email protected] Gdzie wykorzystywane są wskaźniki?. Praca z tablicami Funkcje – zmiana wartości przesyłanych argumentów Dostęp do specjalnych komórek pamięci

Download Presentation

Wyk ł ad 1 : Wskaźniki

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Wyk ad 1 wska niki

Podstawy programowania

Programowanie w C

Wykład 1: Wskaźniki

Dr inż. Zdzisława Rowińska

III p. KIS, pokój 314, [email protected]


Gdzie wykorzystywane s wska niki

Gdzie wykorzystywane są wskaźniki?

  • Praca z tablicami

  • Funkcje – zmiana wartości przesyłanych argumentów

  • Dostęp do specjalnych komórek pamięci

  • Rezerwacja obszarów pamięci


Definiowanie wska nik w

Definiowanie wskaźników

Definiowanie wskaźników:

typ_obiektu *nazwa_wskaźnika;

nazwa_wskaźnikawskazuje na obiektu typu typ_obiektu.

Przykłady

Można definiować wskaźniki do obiektów różnych typów:

int *wi;

char *wch;

float *wf;

  • Uwaga:

  • Z definicji wskaźnika wynika, że wskaźnik pokazuje na obiekt. Referencja nie jest obiektem, dlatego nie można definiować wskaźników do referencji.

  • Wskaźnik, który pokazuje na obiekt jednego typu, nie może być wykorzystany do pokazywania na obiekt innego typu.


Wska niki

Wskaźniki

Sama definicja wskaźnika nie powoduje, że wskaźnik wskazuje na konkretnyobiekt.

Nadanie wartości obiektowi (wskaźnik wskazuje na istniejący obiekt):

int *wi;

int i;

wi=&i; //ustawienie wskaźnika w na obiekt i

Jeśli wskaźnik wskazuje na konkretny obiekt, to można odnosić się do tego obiektuza pomocą wskaźnika. Do operacji tej służy jednoargumentowy operatorodniesienia (wyłuskania, dereferencji) *

*nazwa_wskaźnika;

Przykład:

int *wi; //definicja wskaźnika

int i; //definicja zmiennej i

wi=&i; //ustawienie wskaźnika

*wi=5; //przypisanie wartości 5 zmiennej i


Wska niki cd

Wskaźniki – cd

Przykłady:

int *wi,*wj; //definicja wskaźnika

int i,j; //definicja zmiennych i,j

wi=&i;

i=5;

*wi=5;

j=7;

j=*wi;

wi=&j;

wj=wi;


Wska niki typu void

Wskaźniki typu void

void *wv;

Definicja wskaźnika bez podania typu obiektu, na jaki wskazuje. Może być użytydo wskazywania na obiekty dowolnego typu.

Przykłady:

void *wv;

int *wi;

float *wf;

wv=wi; //teraz wskaźnik wv wskazuje na ten sam obiekt (typu int), //na który wskazuje wskaźnik wi

wv=wf;

wi=wf //kompilator zasygnalizuje błąd!!

wi=(int *)wf; //wykorzystanie rzutowania

wf=(float *)wv; //wykorzystanie rzutowania

Wskaźnikowi typu void można przypisać wskaźnik dowolnego (niestałego) typu.Działanie odwrotne wymaga operatora rzutowania.


Zastosowanie wska nik w do tablic

int *wsk; //definicja wskaźnika

int tab[10]; //definicja tablicy

wsk=&tab[indeks]; //ustawienie wskaźnika na elemencie tablicy //o indeksie indeks

wsk=&tab[0];

wsk=tab;

wsk=&tab[indeks];

wsk=wsk+ind;

wsk +=ind;

instrukcje równoważne

//przesunięcie wskaźnika o ind pozycji

Zastosowanie wskaźników do tablic

Dodanie do wskaźnika liczby całkowitej ind powoduje, że wskaźnik pokazujeo indelementów dalej w tablicy; niezależnie od tego, jakiego typu są elementytablicy.


Zastosowanie wska nik w do tablic1

Zastosowanie wskaźników do tablic

Przykład:

#include <iostream.h>

void main(){

float *wf;

float tab[10];

wf=tab; //lub wf=&tab[0];

for(int i=0; i<10; i++){

*(wf++)=i/10.0;

}

for(i=0,wf=tab;i<10;i++,wf++)

printf(”%f\n”,*wf);

}


Nazwa tablicy i wska nik

Nazwa tablicy i wskaźnik

Nazwa tablicy jest jednocześnie adresem jej zerowego elementu.

Nazwa tablicy jest stałym wskaźnikiem do jej zerowego elementu.

float *wsk;

float tab[10];

wsk=tab; //wsk=&tab[0];

//możliwe jest przypisanie

wsk++;

//niemożliwa jest instrukcja

tab++;

tab[ind];

*(tab+ind);

Wskaźnik jest pewnym obiektem w pamięci (to znaczy posiada swój adres).

Nazwa (również tablicy) nie jest obiektem (nie ma więc adresu).

float *wsk;

&wsk; //adres wskaźnika – odwołanie poprawne


Wska niki w argumentach funkcji

Wskaźniki w argumentach funkcji

void fun(float f) {

f /= 3.3;

}

float fun(float *f) {

*f /= 3.3;

}

Przesyłanie argumentów przez wartość.

Funkcja nie zmienia wartości przesyłanego argumentu.

void main() {

float fvar = 13.3;

fun(fvar);

printf(”%f\n”, fvar); // 13.3

fun(&fvar);

printf(”%f\n”, fvar);// 4.03

}

Przesyłanie argumentówprzez wskaźnik.

Zmiana wewnątrz funkcjiwartości przesyłanegoargumentu.


Przesy anie tablic do funkcji

Przesyłanie tablicdo funkcji

#include <iostream.h>

void f1(int *pi, int rozm);

void f2(int *pi, int rozm);

void f3(int t[], int rozm);

void main(){

int tab[5]={1,2,3,4,5};

f1(tab,5);

f2(tab,5);

f3(tab,5);

}

void f1(int *pi, int rozm){

printf("\nfunkcja f1\t”);

for(int i=0;i<rozm;i++)

printf(”%f\t”,*(pi++));

}

void f2(int *pi, int rozm){

printf("\nfunkcja f1\t”);

for(int i=0;i<rozm;i++)

print(”%f\t”,pi[i]);

}

void f3(int t[], int rozm){

printf("\nfunkcja f3\t”);

for(int i=0;i<rozm;i++)

print(”%f\t”,t[i]));

}

Funkcje są wywoływane przez podanienazwy tablicy

Przesłany adres tablicy inicjalizujelokalny wskaźnik pi. Wewnątrz funkcji- zapis wskaźnikowy

Przesłany adres tablicy inicjalizujelokalny wskaźnik pi. Wewnątrz funkcji - zapis tablicowy

Przesłany adres tablicy odebranyjako tablica


Przesy anie tablic do funkcji cd

Przesyłanie tablic do funkcji – cd

  • Odebranie tablicy jako tablicy – czytelność funkcji

  • Odebranie tablicy jako adresu inicjującego wskaźnik – funkcja działa szybciej

  • Odebranie tablicy jako adresu – łatwiejsze przekazywanie tablic wielowymiarowych (rozmiary tablicy nie muszą być znane w momencie wywołania funkcji)


Wska niki do sta ych

Wskaźniki do stałych

Wskaźniki do stałych mogą zawierać adresy dowolnych zmiennych i mogą być modyfikowane w programie, ale nie można za ich pomocą modyfikować zmiennych wskazywanych.

const int stala = 10;// definicja stałej typu int

const int *wsk_st;// wskaźnik do stałej typu int

void main() {

int i = 5;

const int *w = &i;// wskaźnik zainicjowany

wsk_st = &i;// inicjacja adresem zmiennej automatycznej i

cout << *wsk_st << endl;// 5

cout << *w << endl;// 5

// *w = *w + 5;// błąd kompilatora !

// *wsk_st+= 7;// nie można modyfikować stałej

wsk_st = &stala;// wskaźnik inicjowany adresem stałej

w = &stala;// wskaźnik inicjowany adresem stałej

cout << *wsk_st << endl;// 10

cout << *w << endl;// 10

}


Sta e wska niki

Stałe wskaźniki

Stały wskaźnik to wskaźnik, który zawsze pokazuje na to samo. Wskaźnik tego typu musi być zainicjowany w miejscu definicji - tak jak każda stała. W programie nie można już modyfikować jego wartości.

Za pomocą wskaźnika stałego można jednak modyfikować zawartość zmiennej wskazywanej, ale tylko tej, której adresem wskaźnik został zainicjowany.

const int st = 4;// stała

int zm = 10;// definicja zmiennej

int * const w = &zm;// stały wskaźnik do zmiennej zm

// int * const x = &st;// błąd – wskaźnik musi wskazywać na zmienną

const int * const x = &st;// dobrze - stały wskaźnik do stałej

int i = 7;

int * const wi = &i;// stały wskaźnik do zmiennej lokalnej i

int * const pz = &zm;// stały wskaźnik do zmiennej zm

cout << *wi << endl;// i=7 = i

cout << *pz << *w << endl;// 10 i 10; zm=10

*wi +=8;// i = 7 + 8 = 15

cout << i << endl;// i =15

// wi = &zm;// błąd – nie wolno zmieniać stałej wi

*pz += 2;// zm = 10 + 2

cout << zm << endl;// zm = 12


Wska niki do funkcji

Wskaźniki do funkcji

typ_zwracany(*wsk_do_funkcji)([argumenty_funkcji]);

#include <iostream.h>

void f1();

void f2();

void blad();

void main(){

void (*pf)()=blad;

int i;

cin>>i;

if(i==1) pf=f1;

else if(i==2) pf=f2;

(*pf)();

}

void f1(){

cout<<"funkcja f1\n";

}

void f2(){

cout<<"funkcja f2\n";

}

void blad(){

cout<<"blad\n";

}


Wska niki do funkcji1

Wskaźniki do funkcji

  • Nazwa funkcji jest adresem jej początku (adresem miejsca w pamięci, gdziezaczyna się kod tej funkcji).

  • Zastosowanie wskaźników do funkcji:

  • Przesyłanie argumentów do funkcji. Adres funkcji można wysłać jako argument.

  • Tworzenie tablic ze wskaźników do funkcji.


Wyk ad 1 wska niki

#include <iostream.h>

void f1();

void f2();

void blad();

void funkcja(int i, void (*pf)());

void main(){

void (*pf)()=NULL;

int i;

cin>>i;

funkcja(i,pf);

}

void funkcja(int i, void (*pf)()){

pf=blad;

if(i==1) pf=f1;

else if(i==2) pf=f2;

(*pf)();

}

void f1(){

cout<<"funkcja f1\n";

}

void f2(){

cout<<"funkcja f2\n";

}

void blad(){

cout<<"blad\n";

}

Przesyłanie argumentów do funkcji


Tablice wska nik w

Tablice wskaźników

typ_wskazywany*tablica[rozmiar];

//typ_wskazywany*(tablica[rozmiar]); zapis równoważny

double *tablica[10];


Wyk ad 1 wska niki

Tablice wskaźników - cd

#include <iostream.h>

void f1();

void f2();

void blad();

void main(){

void (*pt[3])()={f1,f2,blad};

for(int i=0;i<3;i++)

(*pt[i])();

}

void f1(){

cout<<"funkcja f1\n";

}

void f2(){

cout<<"funkcja f2\n";

}

void blad(){

cout<<"blad\n";

}

Tablica wskaźników do funkcji


Pami a zmienne w programie

Pamięć a zmienne w programie

Ze względu na czas życia wyróżnia się:

- obiekty statyczne - istniejące od chwili rozpoczęcia działania programu aż do jego zakończenia

- obiekty dynamiczne - tworzone i usuwane z pamięci w trakcie wykonania programu:

- automatycznie, czyli bez udziału programisty

- kontrolowane przez programistę


Pami a zmienne w programie1

Pamięć a zmienne w programie

O tym czy obiekt jest statyczny czy dynamiczny decyduje miejsce deklaracji oraz klasa pamięci (przypisywana jawnie w deklaracji lub przyjmowana domyślnie).

Klasę pamięci określają słowa kluczowe: auto, static, register, umieszczane przed deklaracją zmiennej, np. static int x;

  • wszystkie zmienne globalne są statyczne

  • wszystkie zmienne lokalne zadeklarowane bez jawnego specyfikowania klasy pamięci są automatyczne (auto).

    Zmienną lokalną można uczynić statyczną dodając przed deklaracją static (czasami stosowane w funkcjach)

  • zmienne klasy register są automatyczne


Funkcje malloc calloc free

Funkcje malloc, calloc, free

Dynamiczna alokacja pamięci

W języku C/C++ istnieją standardowe funkcje umożliwiające dynamiczną alokację pamięci (malloc i calloc) oraz funkcja zwalniająca przydzieloną pamięć (free). Prototypy funkcji:

void *malloc(size_t K);// alokacja K bajtów

void *calloc(size_t N, size_t K);// alokacja N razy po K bajtów

void free(void *x);// zwolnienie obszaru

  • Funkcje malloc i calloc przydzielają spójne obszary pamięci, których rozmiary nie przekraczają 64 KB (size_t jest zdefiniowany jako unsigned) i zwracają wskazanie do przydzielonego obszaru.

  • Jeżeli alokacja nie jest możliwa, to zwracany jest wskaźnik NULL. Funkcja calloc dodatkowo zeruje przydzieloną pamięć. Funkcja free zwraca do systemu przydzieloną pamięć.

  • Funkcje malloc i calloc zwracają wskaźniki do typu void dlatego niezbędne są konwersje typu przy podstawieniach do wskaźników innych typów.

  • Należy uważać, aby za pomocą funkcji free nie zwalniać pamięci, która nie została przydzielona.


Funkcje malloc calloc free1

Funkcje malloc, calloc, free

Dynamiczna alokacja pamięci

Przykład:

void main()

{

int i;

char* ps = NULL; //wskaźnik do char

ps = (char*) malloc(5 * sizeof(char)); //alokacja pamięci na

//elementy typu char

if (ps)

{

strcpy(ps, "Ola");

for (i = 0; i < strlen(ps); i++)

printf("%c\n", *(ps + i)); //wypisanie i-tego

//elementu tablicy

free(ps); //zwolnienie pamięci

ps = NULL;

}

}


Wyk ad 1 wska niki

Dynamiczny przydział pamięci - przykładPrzydział pamięci dla n-liczb typu int, wczytanie liczb, obliczenie średniej

#include <stdio.h>

#include <stdlib.h>

int main()

{

int *tab, i, n, x;

float suma = 0.0;

printf("Podaj ilosc liczb: "); scanf("%d",&n);

tab = (int *) calloc(n,sizeof(int));

if (tab == NULL)

{

printf("Nie mozna przydzielic pamieci.\n"); exit(-1);

}

for (i=0; i<n; i++) /* wczytanie liczb */

{

printf("Podaj liczbe nr %d: ",i+1);

scanf("%d",&x); tab[i] = x;

}

for (i=0; i<n; i++) suma = suma + tab[i];

printf("Srednia %d liczb wynosi %f\n",n,suma/n);

free(tab);

return 0;

}


Dynamiczny przydzia pami ci na tablic dwuwymiarow macierz

Dynamiczny przydział pamięci na tablicę dwuwymiarową (macierz):

Zamiast standardowego odwołania do elementów macierzy: tab[i][j]

stosujemy odwołania do odpowiednich elementów wektora:

*(tab+M*i+j) lub tab[M*i+j], gdzie M –liczba kolumn

Przykład:

tablica tab, dla której N=3, M=4

odwołujemy się do elementu tab[2][2]:

*(tab+4*2+2)


Przydzia pami ci na tablic nxm wygenerowanie i wy wietlenie liczb

Przydział pamięci na tablicę NxM, wygenerowanie i wyświetlenie liczb

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define N 4

#define M 6

int main()

{

int i,j,*tab;

tab = (int *) calloc(N*M,sizeof(int));

srand(time(NULL));

for (i=0;i<N;i++)

for (j=0;j<M;j++)

*(tab+M*i+j) = rand()%100;

for (i=0;i<N;i++)

{

for (j=0;j<M;j++)

printf("%4d",tab[M*i+j]);

printf("\n");

}

free(tab);

return 0;

}


Metoda 2 wska nik na tablic wska nik w

Metoda 2 (wskaźnik na tablicę wskaźników):

Przydzielamy pamięć na N-elementowy wektor wskaźników na typ int,

a następnie do kolejnych elementów tego wektora zapisujemy adresy

M-elementowych wektorów liczb typu int

(pamięć na wektory jest także przydzielana dynamicznie)

int **tab;

tab = (int**) calloc(N,sizeof(int *));

for (i=0; i<N; i++)

tab[i] = (int*) calloc(M,sizeof(int));


Przydzia pami ci na tablic nxm wygenerowanie i wy wietlenie liczb1

Przydział pamięci na tablicę NxM, wygenerowanie i wyświetlenie liczb

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define N 4

#define M 6

int main()

{

int i, j, **tab;

tab = (int **) calloc(N,sizeof(int *));

for (i=0;i<N;i++)

tab[i] = (int*) calloc(M,sizeof(int));

srand(time(NULL));

for (i=0;i<N;i++)

for (j=0;j<M;j++)

tab[i][j] = rand()%100;

for (i=0;i<N;i++)

{

for (j=0;j<M;j++)

printf("%4d",tab[i][j]);

printf("\n");

}

for (i=0;i<N;i++)

free(tab[i]); /*w pierwszej kolejności zwalniamy pamięć przydzieloną na N wektorów, każdy o rozmiarze M */

free(tab); /*zwalniamy pamięć przydzieloną na N-elementowy

wektor wskaźnikow na typ int */

return 0;

}


  • Login