C Pointers and Memory Allocation

文章推薦指數: 80 %
投票人數:10人

Arrays are a very convenient way to declare and use collections of data. ... ip = (int *) malloc( sizeof(int)*10 ); // allocate 10 ints CPointersandMemoryAllocation Otherresources About.com'sPointerhelppage About.com'sArrayhelppage About.com'sMemoryAllocationhelppage Pointers Large-scaleprogrammingproblemsgenerallyrequireaprogrammer tomovebeyondsimplevariablesandstartdealingwithcollections ofdata.Usuallythefirstwaythatprogrammersdothisiswith arrays.Arraysareaveryconvenientwaytodeclareanduse collectionsofdata.Butarraysarestatic;theycannotgrowor shrinktothesizethat'sneededforeachparticularuseofthe program. Thisiswherepointerscomein.Pointers(alongwithmemoryallocation) allowyoutocreateprogramsthatcanuseasmuchmemoryasthey need(andnomore). Apointerisareferencetosomeotherpieceofdata.Itis notthedataitself.InC,thevalueinapointerthatrepresents thereferenceisoftencalledanaddress,sincecomputer memoryisaccessedusingaddressesthatdenotewhichmemorylocation isbeingaccessed. Aspecialvalueof0iscalledthenullpointer,alsoknownas NULLand"nil".Ifapointerhasthevalueof0,itis knowntoNOTbepointingatanything. Declarations Apointerisdeclaredbyusingthe*notationaddedto anexistingdatatype.Forexample,"int*"isapointer toaninteger,and"double*"isapointertoadouble. So,thedeclaration int*ip; declaresavariablenamedipthatisapointertoan integer. Creatingavalidpointervalue Onewaytocreateapointervalueistousethe&operator onavariablename.Thisoperatorisknownas"address-of",because that'swhatitdoes--itprovidestheaddressof(inotherwords,a pointerto)thevariableitisappliedto.So,thecode int*ip; intx; x=42; ip=&x; willassign42tox,andwillassigntoipa pointertox. Usingapointer Thebasicoperationthatyouuseapointerwithisthe dereferencingoperation.InC/C++thisisthe* operator.The*followsapointerandreturnsthememory locationthatisbeingpointedto.Attheendoftheaboveblock, *ipwouldrefertothesamememorylocationthatx refersto,andwouldgiveusaccesstothevalue42.So, printf("%d%d\n",x,*ip); wouldprint"4242",sincebothrefertothesamelocation, andhencethesamevalue(thatisstoredinthatlocation). Youcanalsosay *ip=37; andthiswouldupdatethelocationpointedtobyipto containthevalue37.Sincethisisthesamelocationasthe variablexrefersto,ittoonowcontains37. MemoryAllocationandDeallocation Pointersarenotreallyveryusefulwhensimplypointing topre-declaredvariables.Whatreallymakesthemuseful isthatyoucanon-the-flyallocatenewvariablesoutof unusedmemory.Thisallowsaprogramtodealwithvariable amountsofmemory. Thebasicmemoryallocationfunctionismalloc().Its functionprototypeis: (void*)malloc(size_tnumbytes); Whatthismeansisthatittakesasingleargumentthatisthe numberofbytesyouwanttoallocate(size_tisusually thesameasunsignedint),anditreturnsapointerto thatnewmemoryspace.Sincemallocdoesnotknowwhat typeofpointeryouwant,itreturnsapointertovoid, inotherwordsapointertoanunknowntypeofdata. Thetypicalwaythatyouusemallociswithabuilt-in operatorcalledsizeof().sizeof()returnsthe sizeinbytesofaspecifictype,whichisprovidedasaparameter. So,allputtogetherwecandosomethinglike: int*ip; ip=(int*)malloc(sizeof(int)); Wearecallingmallocandaskingittoallocateenoughbytesofmemory toholdoneintegervalue(onmostcomputersthesedays,thiswouldbe4), andwearetakingthepointerreturnedfrommallocandcasting ittobeapointertoaninteger. Pointersandarrays Allocatingindividualintegersisn'tallthatusefuleither.But malloc()canalsoallocatearrays.Wewilldiscussthe similarityofpointersandarraysinclass,andthetextbookdiscusses thisinsection3.13.Butessentially,apointercanbeusedasan array,andyoucanindexitjustlikeanarray,aslongasitis pointingtoenoughmemory.Thefollowingexampledemonstratesthis: int*ip; ip=(int*)malloc(sizeof(int)*10);//allocate10ints ip[6]=42;//setthe7thelementto42 ip[10]=99;//WRONG:arrayonlyhas10elements (thiswouldcorruptedmemory!) Freeingmemory,andmemoryleaks Supposewehadthefollowingcode: int*ip; ip=(int*)malloc(sizeof(int)*10);//allocate10ints ...(usethearray,etc.) ip=(int*)malloc(sizeof(int)*100);//allocate100ints ... ThisisperfectlyvalidCcode--youcanalwaysassignanewvalue toapointervariable,socallingmallocagaintoallocatenewmemory islegitimate.Butwhathappenstothefirstallocatedmemoryof10ints? Theansweristhatitislostforever(atleastuntiltheprogram ends).Thisiscalledamemoryleak.Ifyouallocatememory,and thenchangethepointerthatwaspointingtothatmemory(withoutmaking anycopies),thenyourprogramcannolongeraccessthatmemory,even thoughitisstillallocated. ThesolutiontothisisthatCandC++requireyoutofreethe allocatedmemorywhenyouaredonewithit.Sothecodeaboveshouldbe: int*ip; ip=(int*)malloc(sizeof(int)*10);//allocate10ints ...(usethearray,etc.) free(ip);//de-allocateoldarray ip=(int*)malloc(sizeof(int)*100);//allocate100ints ... Thisprogramdoesnotleakmemory.Itcorrectlyfreestheoldallocation beforeallocatingthenewarray. InJava,thereisnofreefunction.Javaautomaticallycleans upanallocatedmemory.Thisiscalledautomaticgarbagecollection. ButCandC++donothavethis.Youareresponsibleforfreeingany andallmemorythatyourprogramallocates. Pointersandarrays Pointerscanusearrayindexingnotation,orpointerarithmetic notation.Socanarrays.Anarraynameisessentiallya constantpointer. int*p; inta[10]; p=(int*)malloc(sizeof(int)*20); p[2]=100;//set3rdelementinalloc'darrayto100 *(p+2)=100;//samething a[2]=200;//set3rdelementinregularyarrayto200 *(a+2)=200;//samething Pointersandarraysaredifferent,buttheyareaccessedsimilarly ifthepointerisbeingusedtoaccessablockofvalues. However, thearraydeclaresablockofsomedatatypewhileapointeronly declaresspaceforitself(thedataareaneedsmalloc'd) Theaddressofthearray(i.e.,apointertoit)isnotstored anywhere;thecompilerfiguresitoutwhileitiscompiling yourprogram,sowhenyouusethearraynameasapointer,you areessentiallyusingaconstantnumberasanaddress. Pointersandarraysasarguments Theoneplacewherepointersandarraysbecomealmostexactly synonomousiswhentheyareusedasparameterstofunctions. Thisisbecausearraysasargumentspassonlytheaddress ofthearraytothefunction.Inotherwords,arraysas passedaspointers! InC,mostvaluesarepassedusingcall-by-value,which meansthatthefunctiongetsacopyofthevalue.Ifthefunction modifiestheparameter,theoriginalvariableusedasaparameter doesnotgetmodified.However,arraysarepassedcall-by-reference, whichmeansthatareference(i.e.,pointer)tothearrayis passedratherthanthearrayitself. Itwouldbeextremelywastefultocopyawholearraytodocall-by-value onarrays.Whatifthearrayhadamillionelements?Call-by-value wouldbeveryslowinthatcase!Soarraysarepassedcall-by-reference, andthismeansthatifafunctionmodifiesanarrayelement,the elementkeepsthatchangeevenwhenthefunctionisdone. Sincearraysarepassedbyreference,thefunctioncanequallybe declaredinthetwofollowingways: intfunc(intA[]); intfunc(int*A); Bothofthesedeclarationssayessentiallythesamething.Thefirst saysthatanarrayisgoingtobepassedinbyreference,and thereferencetoanarrayissimplyapointertothefirstelement. Thesecondsayswearegoingtogetapointertoaninteger,andwe arelefttoguessthatthepointerwillrefertoanarrayofints. Ifyou...



請為這篇文章評分?