You are on page 1of 34

Uvod u pokazivae u C-u

Pokazivai u C-u

Pokazivai (pointers) su osnovni dio C jezika

Snaan alat koji se esto koristi jer:

se jedino sa pokazivaima mogu izvesti neki


rauni i programske tehnike
se dobiva kompaktni i efikasni kod

Ali nepravilno koritenje =>

velika opasnost od greaka u programu!

"s velikom moi dolazi velika odgovornost"

Memorija raunala

Jednostavan primjer:
(32bit)

00000000
00000001

...
0001C702

Adrese memorijskih lokacija


od 00000000(16) do FFFFFFFF(16)

0001C703

Na svakoj adresi pohranjen


1 byte, dakle broj od 00(16) do FF(16)
(0 do 255)

0001C706

0001C704
0001C705
0001C707
0001C708

...
FFFFFFFE
FFFFFFFF

00
00

...
1A
00
34
00
00
00
00

...
00
00

00000000

Definicija varijabli

definicijom varijable rezerviramo


prostor u memoriji
int a;
char b;
short c;
a = 1;
b = 2;
c = 3;

00000001

...
0001C702

a
a je "na adresi"
0001C702(16)

0001C703
0001C704
0001C705

b
c

za varijablu a su rezervirana 4 bajta


poevi od adrese 0001C702

0001C706
0001C707
0001C708

...
FFFFFFFE
FFFFFFFF

00
00

...
01
00
00
00
02
03
00

...
00
00

Operator &
Kako saznati adresu od x ?
int x=0,y=10;

020BC40A

020BC40B
020BC40C
020BC40D
020BC40E

&x
&y

020BC40A
020BC40E

020BC40F
020BC410
020BC411

& itati "adresa od"

00
00
00
00
0A
00
00
00

Operator &
0001C702

Primjer:

0001C703
0001C704
0001C705

int a;

0001C706

a = 1;

0001C707

printf("a = %i, ",a);

0001C708

printf("adresa od a %x\n",&a);

Ispis:

a = 1, adresa od a je 1C702

01
00
00
00
02
03
00

Pokaziva (pointer)
Kamo pohraniti adresu?

... u pokaziva!

Pokaziva je varijabla koja sadri adresu


int a;

int *pa;

/* pokazivac na int

*/

pa = &a;

/* uzmi adresu od a i pohrani


je u pokazivac pa
*/

Definira se kao i "obina" varijabla, s time


da se prije imena stavi ' * '

Definiranje pokazivaa
(primjeri)
short a, *pa;
a

a = 5;

0001C702
0001C703

pa = &a;

0001C704

printf("%x ",a);

0001C705

printf("%x ",&a);
printf("%x\n",pa);

Ispis:

pa

0001C706
0001C707
0001C708

05
00
02
C7
01
00
00

5 1C702 1C702

Kada pokaziva sadri adresu neke varijable


kae se da "pokazuje" na tu varijablu

Definiranje pokazivaa
int a;
int *pa;

/* pokazivac na int

*/

char *pb; /* pokazivac na char

*/

pa = &a;

/* ok

*/

pb = &a;

/* nije dopusteno!

*/

moraju biti istog tipa

Operator *
(dereferenciranje pokazivaa)
imamo pokaziva koji pokazuje na varijablu a:

int a=25, *pa;


pa=&a;

/* sada pa pokazuje na a */

s operatorom * moemo pristupiti sadraju


memorijske lokacije koja je zapisana u pokazivau

printf("%i",*pa);

Ispis:

25

pristupamo sadraju od a

Operator *
(dereferenciranje pokazivaa)
imamo pokaziva koji pokazuje na varijablu a:

DEFINICIJA

int a=25, *pa;


pa=&a;

/* pa pokazuje na a */

s operatorom * moemo pristupiti sadraju


memorijske lokacije koja je zapisana u pokazivau

printf("%i",*pa);

Ispis:

25

PRISTUP SADRZAJU
(dereferencing)

pristupamo sadraju od a

Operator *
(primjeri)
char x=1,y=2;

Ispis:

char *p;
p=&x;
printf("%i",*p);

p=&y;
printf("%i",*p);

y=3;
printf("%i",*p);

Operator *
(primjeri)
char x=5,*p;
p=&x;

/* p pokazuje na x */

ako pokaziva p pokazuje na x onda je jednako


pisati printf(*p);ili printf(x);

Ispis:
printf(*p);
printf(x);
*p=3;
printf(*p);
printf(x);

5
5
3
3

Operator *
(primjeri)
char x=5,*p;
p=&x;

/* p pokazuje na x */

ako pokaziva p pokazuje na x onda je jednako


pisati printf(*p);ili printf(x);

Ispis:

printf(*p);
printf(x);

5
5

odnose se na sadraj iste


memorijske adrese

Primjeri
adresa od a je
1B60

int a=1,b=2;
int *pa, *pb;
pa=&a;
pb=pa;
*pb=15;
b=*pa+5;

pa

pb

Primjeri
adresa od a je
1B60

int a=1,b=2;

int *pa, *pb;

pa=&a;
pb=pa;
*pb=15;
b=*pa+5;

pa

pb

Primjeri
adresa od a je
1B60

int a=1,b=2;

int *pa, *pb;

pa=&a;

pb=pa;
*pb=15;
b=*pa+5;

pa

pb

1B60

Primjeri
adresa od a je
1B60

int a=1,b=2;

int *pa, *pb;

pa=&a;
pb=pa;
*pb=15;
b=*pa+5;

pa

pb

1B60

1B60

1B60

Primjeri
adresa od a je
1B60

pa

pb

int a=1,b=2;

int *pa, *pb;

pa=&a;

1B60

pb=pa;

1B60

1B60

*pb=15;

15

1B60

1B60

b=*pa+5;

Primjeri
adresa od a je
1B60

pa

pb

int a=1,b=2;

int *pa, *pb;

pa=&a;

1B60

pb=pa;

1B60

1B60

*pb=15;

15

1B60

1B60

b=*pa+5;

15

20

1B60

1B60

Novi primjer (paljivo!)


adresa od a je
1B60

int a=1,b=2;

int *pa, *pb;

pa=&a;
pb=pa;
pb=pa+1;

pa

pb

1B60

1B60

1B60

Novi primjer (paljivo!)


adresa od a je
1B60

pa

pb

int a=1,b=2;

int *pa, *pb;

pa=&a;

1B60

b=a+1;

1B60

1B60

pb=pa+1;

1B60

1B64

ne 1B61 vec 1B64 !

Aritmetika pokazivaa
char
short
int
float

*pc
*ps
*pi
*pf

printf("%x
printf("%x
printf("%x
printf("%x

=
=
=
=

0x00001000;
0x00002000;
0x00003000;
0x00004000;

",pc+1);
",ps+1);
",pi+1);
",pf+1);

Ispis:
1001
2002
3004
4004

Pomak je ovisan o tipu pokazivaa

Polja i pokazivai
...

a[0]

a[1]
10

a[2]
4

a[3]
2

25

...

int x, a[4]={10,4,2,25};
int *pa;
pa = &a[0];

/* pa pokazuje na a[0] */

x = *pa;

/* x = sadrzaj od a[0] */

to sadri x = *(pa+2) ?

Polja i pokazivai
...

a[0]
10
*pa

a[1]

a[2]

a[3]

4
*(pa+1)

2
*(pa+2)

25
*(pa+3)

...

int x, a[4]={10,4,2,25};
int *pa;
pa = &a[0];

/* pa pokazuje na a[0] */

x = *(pa+3); /* isto kao x = a[3] */


printf("%i",x);

Ispis: 25

Polja i pokazivai
...

a[0]
*a
10
*pa

a[1]
*(a+1)
4
*(pa+1)

a[2]
*(a+2)
2
*(pa+2)

a[3]
*(a+3)
25
*(pa+3)

...

Primjer:
int a[4]={10,4,2,25};
int *pa=a;

/* a <=> &a[0] */

for(int i=0;i<4;i++)
printf("%i ",*(pa+i));

Ispis:

10 4 2 25

Najee greke
1) Sintaksa
int x, y = 5;

/* y je na adresi 1BA0 */

int *p = &y;
x = p;

/* mozda greska? */
/* ispravno je x = *p; */

x sada sadri 1BA0

C prevodilac ne radi probleme i stavlja u x


adresu sadranu u p kao da je broj.
Ovakve greke su teke za uoiti

Najee greke
2) Inicijalizacija
VANO: kada se definira pokaziva on ne pokazuje
nigdje, mora se inicijalizirati prije koritenja!
int *p;
*p = 100;

Greka! Moe izazvati


"crash" programa!

int *p;
int x;
p = &x;
*p = 100;

Ok!

Takoer teka za uoiti. Prevodilac ne javlja


greku!

Najee greke
3) Kontrola prije pristupa sadraju
Kada sami ne inicijaliziramo pokaziva, prije pristupa
sadraju valja uvijek kontrolirati ispravnost adrese.
Opasno:
int *p;
p = fun(); /* neka funkcija koja vraca adresu */
*p = 100;

Bolje:
int *p;
p = fun(); /* neka funkcija koja vraca adresu */
if (p!=NULL) *p = 100;

Saetak

Pokaziva je varijabla koja sadri adresu druge


varijable
Pokaziva moe biti bilo kog tipa, ali adrese koje
sadri moraju biti od varijabli istog tipa
Operator & daje "adresu od varijable"
Operator * daje "sadraj lokacije na koju pokaziva
pokazuje"
Pokaziva se definira se kao i obina varijabla ali se
ispred imena stavlja * (Na primjer int *p;)
Obratiti panju da je pokaziva inicijaliziran prije
dereferenciranja (pristupanje sadraju).

Zakljuci

Pokazivai su koristan i snaan alat koji prua veliku


fleksibilnost u programiranju
Opasni su ako se nepravilno koriste!
Snaga i korist pokazivaa dolazi do izraaja u nekim
vanih tehnikama programiranja i dijelovima C jezika
koje nismo vidjeli u ovoj uvodnoj lekciji:
(Dinamiko alociranje memorije, kompleksne strukture
podataka kao npr. vezane liste, stabla i
viedimenzionalna polja promjenljivih veliina, prijenos
argumenata funkcija, kruni buffer-i u memoriji,
pokazivai na funkcije itd.)

Kristijan Lenac
klenac@gmail.com

Polja i pokazivai

to radi ovaj program?

char *grad="akejiR", *p=grad;


while (*p++!=0);
while (p--!=grad) printf("%c",*p);

Ispis ?

Polja i pokazivai

to radi ovaj program?

char *grad="akejiR", *p=grad;


while (*p++!=0);
while (p--!=grad) printf("%c",*p);

Ispis: Rijeka

You might also like