Показивач (програмирање) — разлика између измена

Садржај обрисан Садржај додат
м Враћене измене 2001:4170:2000:1:0:0:0:31 (разговор) на последњу измену корисника …
Ред 169:
* показивачи се не смију међусобно сабирати, множити нити дијелити
 
=== ПрименаПримјена ===
У програмском језику -{C}-, најважније применепримјене показивача су следећесљедеће:
* пренос аргумената функцији ''по референци''
* имплементација низова
Ред 176:
 
====Пренос аргумената функцији по референци====
У програмском језику -{C}-, [[функција (програмирање)|функције]] су такве да добијају увекувијек '''копије''' аргумената које јој прослеђујемопросљеђујемо, а никад оригиналне аргументе. На овај начин функција не може имати спољашње ефекте јер све што добија од функције-позиваоца су копије оригиналних аргумената који остају нетакнути. Овакав начин преноса аргумената се популарно назива ''пренос аргумената по вредностивриједности'', јер функција добија практично само вредностивриједности оригиналних аргумената али никад и директно њих саме.
 
Проблеми се јављају, међутим, у случајевима када желимо да функција ипак измениизмијени одређене промјенљиве које јој проследимопрослиједимо као аргументе. Та се потреба јавља нпр. када желимо функцију која ће имати више резултата, јер помоћу уобичајене кључне речиријечи <code>return</code> она може вратити само један резултат. Тада користимо тзв. ''пренос аргумената по референци'' који у ствари представља праксу да уместоумјесто оригиналног елемента проследимопрослиједимо његову адресу као аргумент. Ова адреса представља показивач на оригинални елемент, па иако се опет поштује правило да функција добија копију аргумента који јој се проследипрослиједи, овај пут она добија копију '''адресе''', што је ипак сасвим довољно да се оригиналном аргументу приђе директно, дереференцирањем.
 
Погледајмо следећисљедећи примерпримјер:
-{<source lang="c">
void povecaj(int c )
Ред 195:
}
</source>}-
Из претходног параграфа закључујемо да функција <code>povecaj</code> неће извршити своју улогу јер на местомјесто променљивепромјенљиве <code>c</code> добија '''копију''' од <code>x</code>. На тај начин копија од <code>x</code> бива повећана за <code>1</code>, али не и оригинални елемент <code>x</code> у функцији <code>main</code>. Да бисмо поправили кôд, мораћемо извршити пар измјена:
* функција <code>povecaj</code> треба да се прилагоди тако да прихвата адресу цјелобројне промјенљиве, а не њу саму
* када добије адресу, дереференцираће је и повећати оно што се налази на тој адреси за <code>1</code>
* функција <code>main</code> треба да пошаље адресу од <code>x</code>, а не сāмо <code>x</code>
Погледајмо како изгледа резултат изменаизмјена:
-{<source lang="c">
void povecaj(int * pc )
Ред 223:
int a[10];
</source>}-
тада настаје <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>a[n]</code> еквивалентно са <code>*(a+n)</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 )