Professional Documents
Culture Documents
ПОКАЖУВАЧИ
ПОКАЖУВАЧИ
Вовед
Пример: int x;
- статички
- динамички
Прашање:
-Каков тип променливи досега сме користеле во програмите? Одговор: Статички
1
Главен дел
ДИНАМИЧКИ ПРОМЕНЛИВИ
ПОКАЖУВАЧ
При преведувањето на програмата потребно е преведувачот да ги знае
сите променливи и нивниот тип. Променливите кои се создаваат за време на
извршување на програмата, а потоа се бришат се нарекуваат динамички
променливи. Динамичките променливи кои добиваат податоци од тип покажувач
се наречени променливи од тип покажувач или само покажувачи. При
креирањето, динамичките променливи се сместуваат во слободната внатрешна
(динамичка) меморија, наречена heap-меморија.
Декларација на покажувачи
тип *име_на_покажувач;
2
(int * pok) или до името на покажувачот (int *pok) - сите наредби ќе имаат ист
ефект.
Операторот & се нарекува адресен оператор. Тој е унарен оператор, кој ја враќа
адресата на операндот по него.
Пример:
int y=5;
int *ypok;
ypok=&y; // на покажувачот ypok му се доделува адресата на променливата у
Оператор за дереференцирање *
Променливата ypok (од предходниот пример) може да се означи и преку
покажувач ypok со *ypok. Во овој случај операторот * се нарекува индиректен
оператор или оператор за дереференцирање – тогаш тој ја враќа вредноста
на променливата на која покажува неговиот операнд.
Иницијализација на покажувачи
Еден покажувач може да се искористи повеќе пати (во една иста програма) и
притоа (во различни моменти) да покажува кон различни променливи од ист
тип и мемориски локации.
3
Примери за користење на операторите & и *
Прашање:
1. Кон што покажуваат покажувачите p и q во следниот програмски сегмент?
int a = 100, b = 200;
int *p = &a, *q = &b;
p = q;
Одговор:
(т.е. и p и q ќе покажуваат кон променливата b).
Пример 1 :
#include <iostream>
using namespace std;
int main()
{
int a=40;
int *pok; //pokazuvac pokazuva na adresata na a
cout<<a<<endl;
pok=&a; //ipa ja sodrzi adresata na a
cout<<pok<<endl; //ja pecati adresata na a
cout<<*pok<<endl; // se pecati 40 bidejki vrednosta na taa adresa e 40
Резултат од програмата:
40
0x22fe44
40
120
0x22fe44
Пример 2:
#include <iostream>
using namespace std;
int main()
{
int a = 5, b = 2;
int *pa = &a, *pb; // иницијализација на покажувач pa, и декларација на покажувач pb
pb = &b; //иницијализација на покажувач рb
*pa = 3;
cout << a << " " << *pa << " " << *pb << endl; // печати 3 3 2
*pb = -1;
cout << b << " " << *pb << endl; // печати -1 -1
*pa = *pb;
cout << a << " " << b << endl; // печати -1 -1
4
return 0;
}
Резултат од програмата:
332
-1 -1
-1 -1
Пример 3:
Што ќе се печати со следната програма?
#include <iostream>
using namespace std;
int main()
{
int x;
int *pok;
x=7;
pok=&x;
cout<<" Adresata na x e" << &x << "\n Vrednosta na pok e " << pok;
cout<<"Vrednosta na x e "<< x << "\n Vrednosta na *pok e "<< *pok;
return 0;
}
Заклучок:
Разликата помеѓу операторите '&' и '*' може да се дефинира како:
Со & се чита и ја враќа адресата на одреден податок.
На пример, &x ја враќа адресата на x.
Со * се чита вредноста покажувана од покажувачот и ја враќа вредноста
која се чува на одредена адреса.
На пример, *p служи за пристап до вредноста покажувана од покажувачот p.
Забелешка:
Големината на еден покажувач зависи од архитектурата на компјутерскиот систем
на кој се извршува програмата и од оперативниот систем: 32-битен компјутерски
систем ќе користи 32-битни мемориски адреси (и, соодветно, покажувачите ќе
зафаќаат 4 бајти податочен простор), додека 64-битен компјутерски систем ќе
користи 64-битни мемориски адреси (и, соодветно, покажувачите ќе зафаќаат 8
бајти податочен простор). Ова на никој начин не влијае на однесувањето на
покажувачите: тие и понатаму можат да се искористат за пристап до податокот на
кој покажуваат - без разлика на неговата големина.
Домашна работа:
Прашања:
1. Одговори на кој тип податоци припаѓаат покажувачите во С++?
1 . Динамички тип. *
5
4 . Структурен тип.
6
2 . int *x; *
3 . int &x;
4 . ptr x;
Вовед
Прашања:
Главен дел
Алокација(резервирање) на меморија
и делокација(празнење) на маморија
Во C++, ова се прави со користење на операторите delete pok (за еден елемент) и
delete[ ] pok (за повеќе елементи).
7
Со неа во меморијата се креира променлива од соодветен тип и на покажувач му
се доделува адресата на креираната променлива. Во спротивно покажувачот
добива вредност NULL.
Пример со наредбите:
int *ip;
ip=new int;
Со наредбата:
delete ip;
се ослободува меморијата на променливата на која покажувал покажувачот ip,
при што тој останува недефиниран.
При бришење на низи се користи наредбата:
delete [ ] pok;
Пример:
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int main() int main()
{ {
int *ip; int N = 100;
ip = new int; parr = new int[N]; //niza od 100
*ip = 2; elementi
cout << *ip << endl; //pecati 2 pок[5] = 3;
delete ip; //se osloboduva memorijata na adresata ip cout << pок[5] << endl; //pecati 3
cout << *ip << endl; delete [] pок;
return 0; return 0;
} }
8
Поради фактот што секој компјутерски систем има ограничено количество на
меморија, понекогаш е можно да не успее динамичкото алоцирање на меморија
(new int[N]). Притоа, доколку системот не успее да резервира доволно количество
меморија, програмата ќе прекине со извршување и ќе јави грешка (runtime error).
Доколку сакаме самите да го решиме проблемот со евентуалниот недостаток на
меморија, тогаш треба да го искористиме специјалниот параметар (nothrow) -
дефиниран во датотеката <new>, и самите да провериме дали алокацијата на
меморија завршила успешно - доколку се случил проблем, покажувачот ќе има
вредност 0 (NULL).
Пример:
#include <iostream>
#include <new>
using namespace std;
int main()
{
int N = 2000000000;
int *pок = new (nothrow) int[N];
if (pокr == 0)
{
cout << "Greshka: Nema dovolno memorija!" << endl;
}
else
{
naredbi so nizata;
}
delete [] pok;
return 0;
}
Домашна работа
1. Кој од наведените резервирани зборови се користи за алоцирање (алокација)
на меморија?
1 . new *
2 . malloc
3 . create
4 . value
9
3 . clear
4 . remove
ОПЕРАТОРИ ЗА ПОКАЖУВАЧИ
Вовед
Веќе кажавме како се користат операторите * и &.
Прашања:
1. Одговори кој е резултатот од извршување на следниот програмски код во
програмскиот јазик С++.
int a = 100, b = 200;
int *p = &a, *q = &b;
p = q;
1 . Покажувачот p покажува кон променливата b *
2 . Вредноста на променливата b се доделува на променливата a.
3 . Вредноста на променливата а се доделувана променливата b.
4 . Покажувачот q покажува конпроменливата а.
10
3 . 2.25 *
4 . Адресата на променливата pr.
Главен дел
Задачи за вежбање:
Пример 1:
Во следниот пример покажувачот pok се користи да покажува кон различни
променливи од ист тип прво кон c, а потоа кон d:
#include <iostream>
using namespace std;
int main()
{
float c = 8.0123, d = 1.12345;
float *pok;
pok = &c;
(*pok) += 2.0; //vrednosta na promenlivata c e zgolemena za 2.0
cout << *pok << endl; //pecati 10.0123
pok = &d; //sega pok ja prima adresata na promenlivata d
(*pok) --; // d se namaluva za 1
cout<< *pok <<endl; // pecati 0.12345
return 0;
}
11
Пример 2:
Определи кој е резултатот од извршување на следната програмa.
#include <iostream>
using namespace std;
int main()
{
double a = 6.125, b = 5.125;
double *p1, *p2;
p1 = &a;
p2 = &b;
(*p1) += 3.0;
*p2 = *p1;
cout <<*p1 << " " << *p2;
return 0;
}
Пример 3:
Определи што ќе се отпечати по извршување на следната програма.
#include<iostream>
using namespace std;
int main()
{
int x[5]={1,2,3,4,5};
int *p=x;
int i;
for(i=0;i<2;i++)
{
int temp=*(p+i);
*(p+i)=*(p+4-i);
*(p+4-i)=temp;
}
for(i=0;i<5;i++) cout<<x[i]<<"\t";
return 0;
}
Пример 4:
Одговори што ќе се прикаже на екранот по извршување на следната програмa.
#include<iostream>
using namespace std;
int main ()
{
int m=10, n=20;
int *p1, *p2;
p1=&m;
p2=&n;
12
*p1+=5;
cout<<"*p1= "<<*p1;
return 0;
}
Пример 5:
Одговори што ќе се прикаже на екранот по извршување на следната програмa.
#include<iostream>
using namespace std;
int main ()
{
int var = 20;
int *ip;
ip = &var;
cout << *ip << endl;
return 0;
}
Пример 6:
Одговори што ќе се прикаже на екранот по извршување на следната програма.
#include<iostream>
using namespace std;
int main ()
{
int m=10, n=20;
int * p1, * p2;
p1=&m;
p2=&n;
*p1+=5;
cout<<"*p1="<<*p1;
return 0;
}
Пример 7:
Определи кој е резултатот по извршување на следнaтa програмa.
#include <iostream>
using namespace std;
int main()
{
int a = 15, b = 2;
int *pa, *pb;
pa = &a;
pb = &b;
*pa = 23;
cout << a << " " << *pa << " " << *pb;
return 0;
}
13
КРЕИРАЊЕ НИЗА ВО ДИНАМИЧКА МЕМОРИЈА СО ПОМОШ
НА ПОКАЖУВАЧИ НА НИЗИ
Вовед
Веќе кажавме дека употребата на покажувачите овозможува флексибилност во
програмирањето, бидејќи покажувачката променлива која ја содржи адресата на
еден динамички податок може да се пренасочи да покажува на друг динамички
податок од ист тип. Не може да покажува на друг тип податок.
int a;
int *pок;
Додека со наредбата:
p=new int;
Главен дел
ПОКАЖУВАЧИ И НИЗИ
Прашања:
14
- Вредноста на почетниот елемент од низата може да се добие со:
*niza или niza[0].
Пример 1:
Пренесување на адресите од една низа во низа со покажувачи и нивно
печатење.
#include <iostream>
using namespace std;
int main ()
{
const int m = 3;
int niza[m] = {10, 100, 200};
int *pok[m];
for (int i = 0; i < m; i++)
pok[i]=&niza[i]; // pok[i] se adresite na elementite od nizata
cout<<"ADRESI VREDNOSTI"<<endl;
cout<<"__________________________"<<endl;
for (int i = 0; i < m; i++)
cout << pok[i]<<" "<<*pok[i] << endl; //pecatenje na adresite i na vrednostite na elementite od nizata
return 0;
}
Пример 2:
Определи што ќе се прикаже на екранот по извршување на следната програма .
#include <iostream>
using namespace std;
int main ()
{
double niza[4] = {1000.0, 2.0, 3.4, 17.0};
double *pok;
pok = niza;
for ( int i = 0; i < 4; i++ )
cout<<*(pok+i)<<endl; //se pecatat elementite od niza
return 0;
}
Пример 3:
Определи што ќе се прикаже на екранот по извршување на следната програма .
#include <iostream>
#include <cstring>
using namespace std;
const int MAX = 4;
int main ()
{
string *ime[MAX] = {“Petar”, “Nikola”, “Tamara”, “Stefan”};
for (int i = 0; i < MAX; i++)
{
cout <<&ime[i]<<” ”<< ime[i] << endl;
}
return 0;
}
Пример 4:
Определи што ќе се прикаже на екранот по извршување на следната програма .
#include <iostream>
using namespace std;
int main ()
{
int number[5];
int * p, n;
p = number; *p = 10;
p++; *p = 20;
p = &number[2]; *p = 30;
16
p = number + 3; *p = 40;
p = number; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << number[n] << ", "; // Се печати 10, 20, 30, 40, 50,
return 0;
}
Пример 5:
Определи што ќе се прикаже на екранот по извршување на следната програма .
#include <iostream>
using namespace std;
int main ()
{
int niza[5] = {10, 100, 200, 3000, 5000};
int i, *pok;
pok = niza;
for ( i = 0; i < 5; i++)
{
cout<<”Adresata na niza [“<<i<<”]=”<< pok;
cout<<”Vrednosta na niza [“<<i<<”]=”<< *pok;
pok++; // придвижување на покажувачот на следна локација
}
return 0;
}
Пример 6:
Определи што ќе се прикаже на екранот по извршување на следната програма .
#include <iostream>
using namespace std;
int main ()
{
int a[5]={1,2,3,4,5};
int *p;
p=a;
cout<<*p<<endl;
return 0;
}
Пример 7:
Определи кој е резултатот по извршување на следната програма.
#include <iostream>
using namespace std;
int main()
{
int a [] = {10, 20, 30, 40, 50, 60, 70};
17
int *pok = a;
for (int i=0; i<5; i++)
{
pok++;
cout << *pok << ", ";
}
return 0;
}
Пример 8.
#include <iostream>
using namespace std;
int main ()
{
int number[5];
int * p, n;
p = number; *p = 10;
p++; *p = 20;
p = &number[2]; *p = 30;
p = number + 3; *p = 40;
p = number; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << number[n] << ", ";
return 0;
}
Пример 9:
А. 5
Б. 1
В. 54321
Г. 345
18
АДРЕСНА АРИТМЕТИКА (АРИТМЕТИКА СО ПОКАЖУВАЧИ)
Вовед
19
Според дадената слика имаме:
Ако се дефинираат два покажувачи кон низата од цели броеви т.е. vPtr1 и vPtr2,
при што vPtr1 е на локација 3000, а vPtr2 е на локација 3008 тогаш со наредбата
vPtr2-vPtr1 ќе се добие 2.
Тоа се добива со формулата (3008-3000)/4 =2 затоа што целите броеви зафаќаат
по 4B.
Пример 1:
Во програмата се печатат адресите и вредностите на низата
#include <iostream>
using namespace std;
int main ()
{
int niza[5];
int n, i, *pok;
cin>>n;
for(i=0;i<n;i++)
cin>>niza[i];
pok = niza;
i=0;
20
while ( pok <= &niza[n-1] ) // sporeduvanje na pokazuvac
{
cout<<"Adresata na niza["<<i<<"]="<< pok<<endl;
cout<<"Vrednosta na niza["<<i<<"]="<< *pok<<endl;
pok++; // pridvizuvanje na pokazuvac na sledna adresa
i++;
}
return 0;
}
Пример 2:
Во програмата се наоѓа најголемиот елемент на една низа цели броеви со помош
на покажувач на низа pok.
#include <iostream>
using namespace std;
int main()
{
int niza[5];
int n, i, *pok, max;
cin>>n;
for(i=0;i<n;i++)
cin>>niza[i];
Покажувач на покажувач
Покажувач на покажувач е форма на повеќекратно покажување кон некоја
променлива. Кога ќе дефинираме покажувач на покажувачот, првиот покажувачот
ја содржи адреса на вториот покажувач, што ја кажува локацијата која ја содржи
вистинската вредност на променливата како што е прикажано на сликата:
Пример 2:
#include <iostream>
using namespace std;
int main ()
{
int v;
int *pок;
int **ppок;
21
v = 3000;
pок = &v;
ppок= &pок;
cout << "Vrednosta na promenlivata e :" << v << endl;
cout << "Vrednosta na pok :" << pok << endl;
cout << "Vrednosta na *pok :" << *pok << endl;
cout << "Vrednosta na ppok :" << ppok << endl;
cout << "Vrednosta na **ppok :" << **ppok << endl;
return 0;
}
ПОКАЖУВАЧИ И ФУНКЦИИ
22
4. Размена на местата на две променливи без покажувач и со покажувач
#include <iostream> #include <iostream>
using namespace std; using namespace std;
void swap(int a,int b) void swap(int *a,int *b)
{ {
int tmp; int tmp;
tmp=a; tmp=*a;
a=b; *a=*b;
b=tmp; *b=tmp;
} }
x=5; x=5;
y=6; y=6;
swap(x,y); swap(&x,&y);
cout<<"x="<<x<<" y="<<y<<endl; cout<<"x="<<x<<" y="<<y<<endl;
return 0; return 0;
} }
6 y=5
int clear3(int *a, int size) int clear4(int a[], int size)
{ {
int i; int* p;
for(i=0;i<size;i++) for(p=&a[0];p<&a[size];p++)
a[i]=0; *p=0;
24
return 0; return 0;
} }
Домашна работа
25
2 . Адреси
3 . Покажувачи
4 . Графови
26
вредност да ја има адресата на променливата х?
1 . p=&x
2 . p=*x
3 . *p=&x
4 . p=**x
27
11. Која вредност ќе се печати по извршување на следниот
програмски сегмент?
int a = 5;
int *p;
p = &a;
*p = 3;
cout << a << endl;
1 . 0
2 . 5
3 . 8
4 . 3
28
1 . 0
2 . 56
3 . 4325
4 . 564325
---------------------------
Која наредба треба да се допише за да покажувачот fun_int
покажува на адресата на променивата а.
1 . fun_int = *a;
2 . fun_int = &a;
3 . *fun_int = &a;
4 . *fun_int = *a;
http://mendo.mk/Lecture.do?id=15
https://www.mk.w3ki.com/cplusplus/pointer_operators.html
29