Показивач (програмирање) — разлика између измена
Садржај обрисан Садржај додат
Нема описа измене |
м Враћене измене 178.148.73.97 (разговор) на последњу измену корисника Thijs!bot |
||
Ред 1:
'''Показивач''' (понекад '''поинтер''', према {{јез-енг|pointer}}) представља [[
Основна својства показивача су:
* показивач може
* преко њега се може добити
* преко њега се може
Када узимамо или
=== Типови показивача ===
У већини програмских језика који подржавају показиваче, показивачи се дијеле на типске и бестипске.
Уз '''типске показиваче''' се веже информација о типу
'''Бестипски показивачи''' немају одређен тип
* није дозвољено дереференцирање (
* није дозвољена показивачка аритметика у језицима у којима је подржана за типске показиваче
Ред 20:
=== Референцирање и дереференцирање ===
Референцирање је процес у којем показивачу
Дереференцирање је процес у којем преко показивача који већ показује на неку меморијску локацију приступамо самој локацији, било ради читања њене
* садржи вриједност која служи за означавање да показивач ни не показује ни на шта (најчешће
* показује на адресу која се не налази у меморијском простору процеса који извршава програм. То су најчешће показивачи са неиницијализованим
=== Показивачка аритметика ===
Ред 31:
== Показивачи у програмском језику -{C}- ==
=== Типови показивача ===
У програмском језику -{[[C]]}-, показивачи се
Поред показивача на ''обичне'' промјенљиве, постоје и показивачи на функције. Показивачи на функције се могу просљеђивати другим функцијама као аргументи и преко њих се могу позивати функције на које показују, што им је и примарна
=== Декларација ===
Типски показивачи се декларишу на
-{<source lang="c">
tip_pokazivaca * ime_pokazivaca;
</source>}-
Прво се наводи тип
Бестипски показивачи се декларишу на
-{<source lang="c">
void * ime_pokazivaca;
Ред 55:
</source>}-
-{<source lang="c">
/* декларација произвољне функције */
Ред 68:
=== Референцирање ===
[[Слика:PointerExample.png|десно|мини|250п|Показивач показује на
Да бисмо
-{<source lang="c">
Ред 77:
Пошто је сврха показивача да чувају адресу неког другог податка, морамо да:
* знамо
* користимо оператор <code>&</code> да бисмо добили адресу дате
* позовемо неку од уграђених функција које нам алоцирају нову меморију и враћају адресу алоцираног простора
Ред 86:
int * p1;
int a = 3;
p1 = 0x4CC7EC5C; /* изузетно је опасно и не препоручује се
p1 = &a; /* користимо оператор & за добијање адресе од a да бисмо је
p1 = malloc(sizeof(int) ); /* користимо функцију malloc да алоцирамо простор величине једне
/* malloc враћа адресу новоалоцираног простора */
</source>}-
Ред 97:
</source>}-
Код показивача на функције важи нешто другачија синтакса референцирања. Ако постоји функција <code>f</code>, и показивач <code>pf</code> декларисан тако да може на њу да показује, онда се референцирање врши једноставном
-{<source lang="c">
pf = f;
Ред 103:
=== Дереференцирање ===
Дереференцирање је процес у којем преко показивача који већ показује на неку меморијску локацију приступамо самој локацији. За ову операцију се користи оператор звјездице (<code>*</code>) испред имена показивачке
-{<source lang="c">
int * p1;
Ред 111:
</source>}-
Показивачи на функције се деференцирају на нешто другачији начин. Заправо, код њих се не може говорити о правом ''дереференцирању'', него радије само о позивању функције преко показивача. Наиме, оног тренутка када је нпр. показивач <code>pf</code> почео да показује на функцију <code>f</code>, он је постао алиас (лажно име, друго име) за функцију <code>f</code>, и користи се равноправно, на исти начин као и сама функција.
-{<source lang="c">
int saberi(int a, int b )
Ред 129:
</source>}-
Слиједи
-{<source lang="c">
int saberi(int x, int y )
Ред 138:
int pozovi(int (*psaberi)(int, int), int x, int y )
{
return psaberi(x, y ); /* позивамо функцију преко показивача, и
}
Ред 150:
=== Показивачка аритметика ===
У показивачкој аритметици програмског језика -{C}- не важе уобичајена правила при рачунању, тј. адресе које показивачи чувају неће се сабирати и одузимати као обични бројеви. Начин рачунања ће заправо зависити од тога који је тип
-{<source lang="c">
Ред 165:
Показивачи се могу и међусобно одузимати, када важе слична правила као код показивача и цијелог броја.
Важе
* показивачи се не
* показивачи се не
===
У програмском језику -{C}-, најважније
* пренос аргумената функцији ''по референци''
* имплементација низова
* имплементација динамичких структура
====Пренос аргумената функцији по референци====
У програмском језику -{C}-, [[функција (програмирање)|функције]] су такве да добијају
Проблеми се јављају, међутим, у случајевима када желимо да функција ипак измијени одређене
Погледајмо
-{<source lang="c">
void povecaj(int c )
Ред 194:
}
</source>}-
Из претходног параграфа закључујемо да функција <code>povecaj</code> неће извршити своју улогу јер на
* функција <code>povecaj</code> треба да се прилагоди тако да прихвата адресу цјелобројне промјенљиве, а не њу саму
* када добије адресу, дереференцираће је и повећати оно што се налази на тој адреси за <code>1</code>
Ред 213:
}
</source>}-
Користећи пренос аргумената по референци, програмер такође штеди на копирању аргумената при позивању једне функције из друге. Ако је аргумент који преносимо велик податак, нпр. [[структура]] од више елемената чија укупна величина превазилази величину показивачке
====Имплементација низова====
[[Слика:PointerArray.gif|десно|мини|Скица уређења низа у меморији]]
У програмском језику -{C}- не постоје низови као уграђени типови. Напротив, они се имплементирају преко осталих уграђених типова и показивача. Ово важи и за једнодимензионалне и вишедимензионалне низове (матрице, коцке итд.).
Сваки низ и -{C}--у се састоји од два физичка дијела - елемената који сачињавају низ и једног показивача који показује на почетак тог низа, тј. његов први елемент (
-{<source lang="c">
int a[10];
Ред 224:
тада настаје <code>10</code> елемената низа (који ниједан нема своје право име), и једна показивачка промјенљива <code>a</code> преко које се приступа свим елементима низа користећи синтаксу <code>a[0]</code> (први елемент, јер у -{C}--у индексирање креће од нуле, а не од јединице), <code>a[1]</code>, <code>a[2]</code>, итд.
Низови се у -{C}--у имплементирају преко показивача захваљујући специфичној показивачкој аритметици. Ако је <code>a</code> показивач на први елемент низа, онда <code>*a</code> представља сам елемент. Даље, пошто показивачка аритметика диктира да <code>a+1</code> буде показивач на сљедећи елемент низа, онда ће <code>*(a+1)</code> представљати сам други елемент низа. Идући даље,
Ако идемо даље, и представимо матрицу реалних бројева <code>М</code> димензија <code>m x n</code>, тада је стање у меморији
* <code>M</code> представља показивач на први елемент низа од <code>m</code> показивача.
* сваки од <code>m</code> показивача показује на по први елемент низа од <code>n</code> реалних бројева (видјети слику десно).
[[Слика:MatrixPointer.png|десно|мини|Скица уређења вишедимензионалног низа (матрице) у меморији]]
Када користимо статичке декларације низова, оваква стања меморије се формирају аутоматски, али је такође могуће формирати их ручно, користећи обичну декларацију показивача и неку од уграђених -{C}--ових функција за алоцирање меморије.
-{<source lang="c">
char ** alocirajMatricu(int m, int n )
Ред 269:
== Показивачи у програмском језику Паскал ==
=== Типови показивача ===
У програмском језику Паскал, показивачи се
Паскал не подржава показиваче на функције.
=== Декларација ===
Типски показивачи се декларишу на
-{<source lang="pascal">
ime_pokazivaca: ^tip_pokazivaca;
</source>}-
Прво се наводи име показивачке
Бестипски показивачи се декларишу на
-{<source lang="c">
ime_pokazivaca: pointer;
</source>}-
=== Референцирање ===
Референцирање је процес у којем показивачу додјељујемо адресу одређене меморијске локације. Да бисмо
* уобичајен оператор
* команду <code>new</code> ради алокације меморије и истовремене
-{<source lang="pascal">
Ред 300:
a: integer;
begin
p1 := @a; (* користимо оператор @ за добијање адресе од a да бисмо је
new(p1) (* користимо команду new да алоцирамо простор величине једне
end.
</source>}-
У случајевима када се жели показати да показивач не чува никакву адресу, тада му
-{<source lang="pascal">
p := nil;
Ред 325:
Показивачка аритметика није подржана у стандардном Паскалу. Постоје поједине екстензије Паскала које дозвољавају показивачку аритметику, као што је -{[[GPC]]}- ([[Гну]]-ова екстензија Паскала). Показивачка аритметика Паскала је и тада једноставна и ограничена. Код ње '''важе''' уобичајена правила при рачунању, тј. адресе које показивачи чувају ће се сабирати и одузимати као обични бројеви, на тај начин додавајући и одузимајући тачно задати број бајтова од адресе коју показивач чува.
Погледајмо
-{<source lang="pascal">
var
Ред 338:
</source>}-
Команде <code>inc</code> и <code>dec</code> служе да повећају односно смање
-{<source lang="pascal">
Ред 345:
</source>}-
Ово
=== Примјена ===
У програмском језику Паскал, показивачи немају превелику
==Показивачи у осталим програмским језицима==
===Ада===
[[Ада (програмски језик)|Ада]] подржава само типске показиваче и конверзија између показивача различитих типова је подржана само у одређеном броју случајева. Сви показивачи се
===-{C++}-===
Ред 358:
===-{C#}-===
У програмском језику -{C#}-, показивачи су подржани али само под одређеним условима: било који блок кода који садржи показиваче мора бити означен као „несигуран“, користећи кључну
===Фортран===
|