POKAZIVAČI U JEZIKU C
Pokazivači su jedna od najmoćnijih osobina programskog jezika C. Oni omogućavaju direktan rad sa memorijom, što povećava efikasnost programa i omogućava manipulaciju podacima na niskom nivou.
Šta su pokazivači?
Pokazivač je promenljiva koja čuva memorijsku adresu druge promenljive. Umesto da sadrži stvarnu vrednost, pokazivač pokazuje na mesto u memoriji gde se ta vrednost nalazi.
Svaki podatak koji se koristi u nekom programu mora biti definisan, tj. za njega se mora rezervisati memorija. Dodela vrednosti nekom podatku znači da se ta vrednost u binarnom obliku smesti na određenu memorijsku lokaciju. Pri tome je za podatak zauzeto onoliko bitova memorije koliko se zauzima za određeni tip podatka. Npr. za podatak tipa int u jeziku C to bi bilo 16 ili 32 bita.
Svaka memorijska lokacija ima neku svoju adresu. To je broj pridružen nekoj lokaciji. Najmanja memorijska lokacija koja može samostalno da se adresira je obično jedan bajt.
Pokazivač je prost podatak u koji može da se smesti adresa neke lokacije u memoriji.
Podaci na koje pokazuju pokazivači mogu biti različitih tipova.
Svaka memorijska lokacija ima neku svoju adresu. To je broj pridružen nekoj lokaciji. Najmanja memorijska lokacija koja može samostalno da se adresira je obično jedan bajt.
Pokazivač je prost podatak u koji može da se smesti adresa neke lokacije u memoriji.
Podaci na koje pokazuju pokazivači mogu biti različitih tipova.
Kada neki podatak zauzima više bajtova, pod adresom podatka podrazumeva se bajt sa najmanjim rednim brojem.
Adresa nekog podatka u memoriji može da se dobije pomoću prefiksnog unarnog operatora &. Pogledaj više o operatorima na stranici Operatori u C jeziku.
Adresa nekog podatka u memoriji može da se dobije pomoću prefiksnog unarnog operatora &. Pogledaj više o operatorima na stranici Operatori u C jeziku.
Definisanje pokazivača
* identifikator_pokazivača
Posmatrajmo sledeći kod:
Posmatrajmo sledeći kod:
#include <stdio.h> int main() { int a = 1; // Deklaracija i inicijalizacija promenljive int *pint; // Deklaracija pokazivača na int pint = &a; // Pokazivač dobija adresu promenljive a printf("%d\n", a); // Ispis vrednosti promenljive a printf("%p\n", (void*)pint); // Ispis adrese promenljive a return 0; // Kraj programa } |
Na standardnom izlazu:
|
Uveden je celobrojni podatak a i inicijalizovan na vrednost 1. Takođe je uveden i pokazivac pint na celobrojni podatak i on je inicijalizovan sa memorijskom adresom podatka a. Primetimo da se prilikom štampanja vrednosti pokazivača dobija veliki broj u heksadecimalnom zapisu. Adrese u memoriji su obično ovakve vrednosti.
Opis tipa podatka na početku deklarativne naredbe označava tip pokazivanog podatka. U prethodnom je to int tj. pokazivač pokazuje na ceo broj. Ukoliko bi podatak bio tipa double onda bi se pokazivač na podatak tipa double definisao i inicijalizovao na sledeći način:
double x =2;
double *pdb;
pdb= &x;
Dodela vrednosti podatku preko pokazivača na drugi podatak
Ako bi smo želeli da u prethodnom primeru uvedemo još jedan podatak tipa double npr. y i da inicijalizujemo ovu vrednost koristeći pokazivač na x, dodali bi sledeći kod:
Ako bi smo želeli da u prethodnom primeru uvedemo još jedan podatak tipa double npr. y i da inicijalizujemo ovu vrednost koristeći pokazivač na x, dodali bi sledeći kod:
double x=2;
double *pdb;
pdb= &x;
double y;
y= *pdb; //y je sada 2
Adresna aritmetika
U jeziku C/C++ dozvoljene su sledeće operacije nad pokazivačima:
- dodela vrednosti jednog pokazivača drugom
- dodavanje celobrojnog podatka na vrednost pokazivača i oduzimanje celobrojnog podatka od vrednosti pokazivača
- oduzimanje i upoređivanje dva pokazivača
- upoređivanje pokazivača nulom
Zašto koristiti pokazivače?
- Omogućavaju efikasniju manipulaciju nizovima i stringovima.
- Koriste se za dinamičku alokaciju memorije.
- Omogućavaju direktan rad sa memorijom i optimizaciju koda.
- Ključni su za rad sa funkcijama koje vraćaju više vrednosti i rade sa strukturama podataka poput povezanih listi.
Pokazivači i nizovi
Pretpostavimo da je definisan sledeći niz celih brojeva:
int A[7]={5,-2,3,8,11,0,25};
Da bi ispisali elemente niza korišćenjem pokazivača uvešćemo pokazivač pA i inicijalizovati ga memorijskom adresom prvog elementa niza:
int * pA = A ;
Da bi odštampali vrednost elementa niza na koji pokazivač pokazuje treba upotrebiti *pA:
printf("%d\n",*pA);
Da bi pokazivač menjao element na koji pokazuje tokom izvršavanja petlje, potrebno ga je inkrementirati, tj. povećati njegovu vrednost za 1:
pA++;
printf("%d\n",*(pA));
printf("%d\n",*(pA));
ili:
printf("%d\n",*(pA+i));
U prvom ciklusu, za i = 0 vrednost pokazivača, tj. adresa prvog elementa niza ima vrednost npr. 0xfdf0(heksa decimalni broj) vidi sliku 3. U svakom ciklusu vrednost pokazivača se pomeri za 1(pA++), što znači da će nova adresa biti veća za veličinu podatka u bajtovima na koji pokazuje pokazivač. Ta veličina u ovom slučaju iznosi 4 (int podatak ima veličinu od 4 bajta). Ova vrednost bi se dobila i sa sizeof(int).
U 4. ciklusu npr. i = 3, pa će vrednost memorijske adrese biti veća za 3*4=12 bajta, što je takođe prikazano na slici.
U 4. ciklusu npr. i = 3, pa će vrednost memorijske adrese biti veća za 3*4=12 bajta, što je takođe prikazano na slici.
gde se promenljiva "i" menja tokom ciklusa.
Kompletan kod se može videti u nastavku:
Kompletan kod se može videti u nastavku:
#include <stdio.h> int main() { int A[7] = {5, -2, 3, 8, 11, 0, 25}; int *pA = A; // Pokazivač na prvi element niza for (int i = 0; i < 7; i++) { printf("%p\n", (pA + i)); // Ispis adrese elementa printf("%d\n", *(pA + i)); // Ispis vrednosti elementa } return 0; }
Ako pokrenemo debuger i zaustavimo program unutar petlje, možemo da analiziramo kako se vrednost adrese, na koju pokazuje pokazivač menja tokom ciklusa, kada se vrednost pokazivača promeni za 1. Za i = 3 pokazivač se pomera, tako da pokazuje na 4. element u nizu, a to znači, da se adresa uvećala za 3 * 4 bajta, tj. sa vrednosti 0x61fdf0(0 je završna) promeni se na 0x61fdfc(c je završno i to predstavlja broj 12 u heksadecimalnom sistemu).
Pokazivači i stringovi
Neka je zadat string, odnosno niz char podataka na sledeći način:
char tekst[17]= "Danas je lep dan";
Elementi ovog niza su znakovi, s tim što je poslednji znak '\0'. Više o stringovima u jeziku C pročitajte u članku: C Stringovi.
Da bi ispisali te znakove na ekranu, koristićemo petlju, a character-ima pristupiti pomoću pokazivača. Definišimo pokazivač na podatak tipa char i inicijalizujmo ga memorijskom adresom prvog elementa niza tekst:
Da bi ispisali te znakove na ekranu, koristićemo petlju, a character-ima pristupiti pomoću pokazivača. Definišimo pokazivač na podatak tipa char i inicijalizujmo ga memorijskom adresom prvog elementa niza tekst:
char* ptr = tekst;
Upotrebićemo while petlju, a znakovima pristupiti koristeći pokazivač na podatak tipa char. Kompletan kod je prikazan ispod.
#include <stdio.h> int main() { char tekst[17] = "Danas je lep dan"; // Inicijalizacija niza karaktera char* pTekst = tekst; // Pokazivač na prvi element niza while (*pTekst != '\0') { // Petlja se izvodi dok ne naiđe na null terminator printf("%c\n", *pTekst); // Ispisuje znak na koji pokazuje pokazivač pTekst++; // Pomeranje pokazivača na sledeći znak } return 0;; // Kraj programa }
Uslov koji se ispituje u while petlji je da vrednost koda tekućeg character-a bude različita od vrednosti koda poslednjeg character-a, dakle, da bude različit od '\0'.
Pomeranje pokazivača, da pokazuje na sledeći znak, se ostvaruje povećanjem vrednosti pokazivača za 1. U ovom slučaju dužina char podatka je 1 bajt, pa će se adresa na koju pokazuje pokazivač promeniti u svakom ciklusu za 1 bajt a ne za 4 bajta, što je bio slučaj kod podataka tipa int.
Posle izvršenja programa, prikazaće se:
Pomeranje pokazivača, da pokazuje na sledeći znak, se ostvaruje povećanjem vrednosti pokazivača za 1. U ovom slučaju dužina char podatka je 1 bajt, pa će se adresa na koju pokazuje pokazivač promeniti u svakom ciklusu za 1 bajt a ne za 4 bajta, što je bio slučaj kod podataka tipa int.
Posle izvršenja programa, prikazaće se:
Primeri upotrebe pokazivača
1. Osnovni primer: Deklaracija i dereferenciranje pokazivača
Ovaj primer prikazuje kako deklarisati pokazivač, dodeliti mu adresu promenljive i dereferencirati ga da bismo dobili vrednost.
#include <stdio.h> int main() { int a = 10; // Inicijalizacija promenljive int* p = &a; // Pokazivač p dobija adresu promenljive a printf("Vrednost promenljive a: %d\n", a); printf("Adresa promenljive a: %p\n", &a); printf("Vrednost na koju pokazuje p: %d\n", *p); printf("Adresa na koju pokazuje p: %p\n", p); return 0; // Kraj programa }
Objašnjenje: *p dereferencira pokazivač i vraća vrednost na koju pokazuje.
2. Pokazivači i nizovi
Ovaj primer prikazuje kako pokazivači mogu da manipulišu nizovima.
#include <stdio.h> int main() { int niz[] = {10, 20, 30, 40, 50}; int* p = niz; // Pokazivač na prvi element niza printf("Prvi element: %d\n", *p); printf("Drugi element: %d\n", *(p + 1)); // Pomera pokazivač za jedno mesto printf("Treći element: %d\n", *(p + 2)); return 0; // Kraj programa }
Objašnjenje: Pokazivač p pokazuje na prvi element niza, a pomeranje p + 1 pokazuje na sledeći element.
3. Pokazivači i funkcije (prosleđivanje pokazivača)
Ovaj primer prikazuje kako možemo proslediti pokazivač funkciji da bismo izmenili vrednost promenljive.
#include <stdio.h> void promeniVrednost(int *p) { *p = 100; // Promena vrednosti promenljive kroz pokazivač } int main() { int broj = 50; printf("Pre promene: %d\n", broj); promeniVrednost(&broj); printf("Posle promene: %d\n", broj); return 0; }
Objašnjenje: Funkcija promeniVrednost menja vrednost originalne promenljive pomoću pokazivača.
4. Dinamička alokacija memorije sa pokazivačima
Ovde koristimo malloc za dinamičku alokaciju memorije.
#include <stdio.h> #include <stdlib.h> int main() { int *p; p = (int*) malloc(5 * sizeof(int)); // Alocira prostor za 5 celih brojeva if (p == NULL) { printf("Alokacija memorije nije uspela.\n"); return 1; } for (int i = 0; i < 5; i++) { p[i] = i * 10; } for (int i = 0; i < 5; i++) { printf("Element %d: %d\n", i, *(p + i)); } free(p); // Oslobađanje memorije return 0; }
Objašnjenje: Koristimo malloc za dodelu memorije i free da bismo oslobodili memoriju.
5. Pokazivači na funkcije
Ovde koristimo pokazivač na funkciju da bismo pozvali različite funkcije dinamički.
#include <stdio.h> void hello() { printf("Zdravo, svete!\n"); } void bye() { printf("Doviđenja!\n"); } int main() { void (*fptr)(); // Deklaracija pokazivača na funkciju fptr = hello; // Pokazivač sada pokazuje na hello() fptr(); // Poziv funkcije fptr = bye; // Pokazivač sada pokazuje na bye() fptr(); // Poziv funkcije return 0; }
Objašnjenje: Pokazivač fptr može pokazivati na različite funkcije i pozivati ih dinamički.
Primeri za samostalan rad
ZADATAK 1: Osnovna manipulacija pokazivačima
Tekst zadatka:Napiši program koji koristi pokazivač da promeni vrednost promenljive. Program treba da:
- Deklariše promenljivu x tipa int i dodeli joj vrednost 10.
- Deklariše pokazivač p koji pokazuje na x.
- Korišćenjem pokazivača, promeni vrednost x na 20.
- Prikaže početnu i izmenjenu vrednost x.
Instrukcije za rešavanje:
- Koristi int promenljivu za skladištenje vrednosti.
- Kreiraj pokazivač koji čuva adresu te promenljive.
- Upotrebi operator * (dereferenciranje) da izmeni vrednost promenljive preko pokazivača.
Uputstvo za rešavanje zadatka:
- Deklarišite promenljivu
x
tipaint
i dodelite joj početnu vrednost 10. - Deklarišite pokazivač
p
koji će čuvati adresu promenljivex
. - Pomoću pokazivača promenite vrednost promenljive
x
na 20. - Koristite
printf
za prikaz početne i izmenjene vrednosti promenljivex
.
#include <stdio.h>
int main() {
}
int main() {
// Deklaracija promenljive x i dodela početne vrednosti
int x = 10;
// Prikaz početne vrednosti
printf("Početna vrednost x: %d\\n", x);
// Deklaracija pokazivača p i dodela adrese promenljive x
int *p = &x;
// Promena vrednosti x pomoću pokazivača
*p = 20;
// Prikaz izmenjene vrednosti
printf("Izmenjena vrednost x: %d\\n", x);
return 0;int x = 10;
// Prikaz početne vrednosti
printf("Početna vrednost x: %d\\n", x);
// Deklaracija pokazivača p i dodela adrese promenljive x
int *p = &x;
// Promena vrednosti x pomoću pokazivača
*p = 20;
// Prikaz izmenjene vrednosti
printf("Izmenjena vrednost x: %d\\n", x);
}
ZADATAK 2: Zamena vrednosti pomoću pokazivača
Tekst zadatka:Napiši program koji koristi funkciju i pokazivače za zamenu vrednosti dve promenljive.
- Deklariši dve int promenljive i dodeli im proizvoljne vrednosti.
- Kreiraj funkciju zameni koja uzima pokazivače na te dve promenljive i menja im vrednosti.
- Prikaži vrednosti pre i posle zamene.
Instrukcije za rešavanje:
- Kreiraj funkciju koja koristi pokazivače kao argumente.
- U funkciji zameni vrednosti pomoću privremene promenljive.
- Koristi & za prosleđivanje adresa funkciji.
Uputstvo za rešavanje zadatka:
- Deklarišite dve promenljive tipa
int
i dodelite im proizvoljne vrednosti. - Kreirajte funkciju
zameni
koja prima pokazivače na ove dve promenljive. - Unutar funkcije
zameni
koristite pomoćnu promenljivu za zamenu vrednosti. - Prikažite vrednosti promenljivih pre i posle poziva funkcije
zameni
.
#include <stdio.h>
// Funkcija za zamenu vrednosti pomoću pokazivača
void zameni(int *a, int *b) {
int main() {
}
// Funkcija za zamenu vrednosti pomoću pokazivača
void zameni(int *a, int *b) {
// Pomoćna promenljiva za zamenu
int temp = *a;
*a = *b;
*b = temp;
}int temp = *a;
*a = *b;
*b = temp;
int main() {
// Deklaracija i inicijalizacija promenljivih
int x = 5, y = 10;
// Prikaz početnih vrednosti
printf("Pre zamene: x = %d, y = %d\\n", x, y);
// Poziv funkcije za zamenu
zameni(&x, &y);
// Prikaz vrednosti nakon zamene
printf("Posle zamene: x = %d, y = %d\\n", x, y);
return 0;int x = 5, y = 10;
// Prikaz početnih vrednosti
printf("Pre zamene: x = %d, y = %d\\n", x, y);
// Poziv funkcije za zamenu
zameni(&x, &y);
// Prikaz vrednosti nakon zamene
printf("Posle zamene: x = %d, y = %d\\n", x, y);
}
ZADATAK 3: Ispis elemenata niza pomoću pokazivača
Tekst zadatka:Napiši program koji koristi pokazivač za ispis elemenata niza.
- Deklariši niz brojevi od 5 celih brojeva.
- Inicijalizuj pokazivač p tako da pokazuje na prvi element niza.
- Ispisuj elemente niza koristeći pokazivač i aritmetiku pokazivača.
Instrukcije za rešavanje:
- Inicijalizuj pokazivač na početak niza (p = niz).
- Koristi p + i za pristup elementima niza.
- Dereferenciranjem pokazivača (*(p + i)) ispiši vrednosti.
Uputstvo za rešavanje zadatka:
- Deklarišite niz brojeva sa 5 elemenata i inicijalizujte ga proizvoljnim vrednostima.
- Deklarišite pokazivač
p
i inicijalizujte ga tako da pokazuje na prvi element niza. - Koristite petlju za prolazak kroz niz, pri čemu pokazivač
p
koristite za pristup svakom elementu. - Koristite aritmetiku pokazivača (uvećanje pokazivača) za prelazak na sledeći element niza.
- Prikažite svaki element niza koristeći pokazivač.
#include <stdio.h>
int main() {
int main() {
// Deklaracija i inicijalizacija niza
int brojevi[5] = {1, 2, 3, 4, 5};
// Deklaracija pokazivača
int *p = brojevi;
// Ispis elemenata niza pomoću pokazivača
printf("Elementi niza su:\\n");
for (int i = 0; i < 5; i++) {
return 0;
}
int brojevi[5] = {1, 2, 3, 4, 5};
// Deklaracija pokazivača
int *p = brojevi;
// Ispis elemenata niza pomoću pokazivača
printf("Elementi niza su:\\n");
for (int i = 0; i < 5; i++) {
printf("%d\\n", *p);
p++; // Prelazak na sledeći element
}p++; // Prelazak na sledeći element
return 0;
ZADATAK 4: Suma elemenata niza pomoću pokazivača
Tekst zadatka:Napiši program koji koristi pokazivač za izračunavanje sume elemenata niza.
- Deklariši niz brojevi od 5 celih brojeva.
- Kreiraj funkciju izracunajSuma koja uzima pokazivač na niz i njegovu dužinu.
- Izračunaj sumu elemenata koristeći pokazivač i vrati rezultat.
- Prikaži sumu u main funkciji.
Instrukcije za rešavanje:
- Prosledi pokazivač na prvi element niza funkciji.
- Koristi aritmetiku pokazivača da prolaziš kroz niz.
- Akumuliraj sumu koristeći dereferenciranje pokazivača.
Uputstvo za rešavanje zadatka:
- Deklarišite niz brojeva sa 5 elemenata i inicijalizujte ga proizvoljnim vrednostima.
- Kreirajte funkciju
izracunajSuma
koja:- Kao parametre prima pokazivač na niz i njegovu dužinu.
- Koristi petlju za prolazak kroz niz pomoću pokazivača.
- Akumulira sumu elemenata u pomoćnoj promenljivoj.
- Vraća sumu kao rezultat.
- U glavnoj funkciji
main
, pozovite funkcijuizracunajSuma
i prikažite rezultat.
#include <stdio.h>
int izracunajSuma(int *niz, int duzina) {
int main() {
int izracunajSuma(int *niz, int duzina) {
int suma = 0;
for (int i = 0; i < duzina; i++) {
return suma;
}for (int i = 0; i < duzina; i++) {
suma += *niz; // Dodavanje vrednosti na koju pokazivač ukazuje
niz++; // Prelazak na sledeći element
}niz++; // Prelazak na sledeći element
return suma;
int main() {
// Deklaracija i inicijalizacija niza
int brojevi[5] = {1, 2, 3, 4, 5};
// Pozivanje funkcije za izračunavanje sume
int suma = izracunajSuma(brojevi, 5);
// Ispis rezultata
printf("Suma elemenata niza je: %d\\n", suma);
return 0;
}
int brojevi[5] = {1, 2, 3, 4, 5};
// Pozivanje funkcije za izračunavanje sume
int suma = izracunajSuma(brojevi, 5);
// Ispis rezultata
printf("Suma elemenata niza je: %d\\n", suma);
return 0;
Prethodno
|< C Stringovi |
Sledeće
Funkcije u C >| |