unit 9: programmiersprache c – zeiger und felder · andreas polze 5 pointer (zeiger) • ein...
TRANSCRIPT
AndreasPolze 1
Programmiertechnik1
Unit9:ProgrammierspracheC–ZeigerundFelder
AndreasPolze 2
Ablauf
• HeapundStack• ZeigerundAdressen• ZeigerundFunktionen(-argumente)• ZeigerundArrays• Adreßarithmetik• Beispiel:mallocundAlgorithmenzurSpeicherallokation• MehrdimensionaleFelder• InitialisierungvonFeldern• Kommandzeilenbearbeitung• Funktionszeiger• KomplizierteDeklarationen
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 3
SpeichereinesUNIX-Prozesses• VirtuellerSpeicher
– 232 Adressenoder264 Adressen– proProzess– Aufteilunguserspace/kernelspace
• Benutzerprozessin32-bitOSkann231 Byte=2GBadressieren• Zumindestbei64-bitOSgiltuserspace>>physischerHauptspeicher
• C-ProgrammebenutzensymbolischeNamenfürSpeicheradressen– StatischeVariablen
• Blockstaticstorage,bss
– Lokale(automatische)Variablen• AufdemStackangelegt
– DynamischallozierteSpeicherbereiche• AufdemHeapangelegt– malloc(),brk(),sbrk()
– GemeinsambenutzteSpeicherbereiche• mmap()• Sharedlibraries
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
stack
heap
bss
text
UNIXklassisch
Linux heute
AlleSpeicheradressen
ineinemC-ProgrammsindvirtuelleAdressen
AndreasPolze 4
Dynamik
• GrößederinitialisiertenstatischenVariablenzurCompile-Zeitbekannt– CompilerkannCodezurInitialisierungvonbssgenerieren– Laufzeitsystem(crt0.o)undLoaderführendiesenCodeaus
• GrößedesStacksändertsichdynamisch– JederFunktionsaufrufspeichertVariablenaufdemStack
• Rücksprungadresse,Rückgabewert• Parameter,lokaleVariablen
– Lokalität,Sichtbarkeit– WiegroßsollteStackidealerweisesein?
• DatenaufdemHeapwerdenzurProgrammlaufzeitangelegt– malloc()-,free()-Systemaufrufe
• UnabhängigvonFunktionsverschachtelung• ProgrammiereristfürAllokation/FreigebenvonSpeicherverantortlich
– ReferenzierungvonSpeicheraufdemHeapüberPointer
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 5
Pointer(Zeiger)
• EinPointeristeineVariable,diedieAdresseeinerVariablenenthält– InCexzessivbenutzt– FelderwerdeninCdurchVerweisaufdenFeldanfangdargestellt
– Bsp:4-byteZeigerpverweistauf1-bytecharc• Adressensindarchitekturabhängig(16,32,64bit)• Speicheristbyte-adressierbar
– EinstelligerOperator&ergibtdieAdresseeineObjekts• charc;
char*p=&c;/*Initialisierung*/
– EinstelligerOperator*bewirktDereferenzierung(indirectionoperator)• chard=*p; /*KopierendesWertesvonc*/
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
Adressraum
||| ||||||
p c
AndreasPolze 6
Zeiger– DeklarationundBenutzung
• EinBeispiel:intx=1,y=2,z[10];int*ip; /*ipisteinZeigeraufeinObjektvomTypint*/
ip=&x; /*ipverweistnunaufx */y=*ip; /*ywirdzu1 */*ip=0; /*xwirdzu0 */ip=&z[0]; /*ipverweistnunaufz[0] */
• Mnemonic:- int*ip;– Bedeutung:*ipistvomTypint
• Zeigersindeingeschränkt:könnennuraufObjekteeinesvereinbartenTypsverweisen• Ausnahme:„pointertovoid“(void*)– einbeliebigerZeiger;keineDereferenzierung
– CompilerüberprüftpassendeVerwendungvonZeigern• *ipisteinintundkannsoverwendetwerden: *ip=*ip+10;
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 7
Zeiger(contd.)
• Operatoren*,&– bindenStärkeralsarithmetischeOperatoren(Vorrang)
Bsp:y=*ip+1; /*yenthältdenum1erhöhtenWertaufdenipverweist*/*ip+=1; /*Variable,aufdieipverweistwirdinkrementiert */++*ip; /*ebenso*/iq=ip; /*Zuweisung;iqverweistnunaufgleicheAdressewieip*/(*ip)++;
• KlammernsindwegenAssoziativitätdereinstelligenOperatorennötig
*ip++;• Hierwürdeerstipinkrementiertunddanachdereferenziert
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
||| ||||||
ip
AndreasPolze 8
ZeigerundFunktionsargumente
• CkenntnurWerteparameter(pass-by-value)– KeinedirekteMöglichkeitfüreineFunktion,WerteimAufruferzuändern– ÜbergabederAdresseeinerVariablenermöglichtgerufenerFunktion,
dieseVariablezuändern
– Bsp:• VertauschenderWertezweierVariablen• swap(&a,&b);
voidswap(int*px,int*py){inttemp=*px;*px=*py;*py=temp;
}
• ZeigerermöglichenZugriffaufObjekteimAufrufer
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
a
b
px
py
Aufrufer
swapgetint.c
AndreasPolze 9
ZeigerundFelder
• EngeBeziehungzwischenZeigernundFeldern:– JedeOperation,diedurchFeldindizierungausgedrücktwerdenkann,kann
auchalsZeiger-Operationdargestelltwerden.– Zeiger-Operationensindhäufigschneller
• Beispiel:– inta[10];
– int*pa=&a[0];
– x=*pa;/*kopierta[0]*/
– y=*(pa+1);/*kopierta[1]*/
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
pa
papa+1
pa+2
AndreasPolze 10
ZeigerundFelder(contd.)
• *(pa+3)– verweistaufviertesFeldelement– UnabhängigvomTypderimFeldgespeichertenElemente
• „Zeigerum1erhöhen“– BedeutungistabhängigvomTyp,aufdenderZeigerverweist– Besser:ZeigeraufdasnächsteObjekt„vorrücken“
• Bsp:4-byteint*pa;à (pa+1)bewirkteinerErhöhungum4Byte
• Index-OperationenundZeigeroperationensindsehrähnlich:– WerteinerArray-VariablenistperDefinitiondieAdressedeserstenElements– pa=&a[0];
• Bewirkt,dasspaundaidentischeWertehaben• Äquivalentzupa=a;
– Referenza[i]• Kanngeschriebenwerdenals*(a+i);- beideFormensindäquivalent
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 11
ZeigerundFelder(contd.)
• Array!=Pointer– ZeigervariablekanninAusdrückenlinksstehen(lvalue)– FeldersindkeineVariablen
chara[5];char*pa=a;pa++; /*legal */a=pa; /*illegal */
– SindFelderFunktionsargumente,sowirdAdressedeserstenElementsübergeben.– Bsp:strlen()operiertaufeigenerlokalerKopiedesZeigers
intstrlen(char*s){intn;for(n=0;*s!='\0';s++)n++;returnn;
}– GültigeVerwendungen:
strlen(”helloworld”); /*Zeichenkettenkonstante*/strlen(array); /*chararray[100];*/strlen(ptr); /*char*ptr;*/
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
strlen.c
AndreasPolze 12
FormaleArgumente
• ZeigeralsFunktionsargumente– FolgendeDeklarationensindsyntaktischäquivalent
• func(chars[]);• func(char*s);
– Variante1istbesserlesbar;bevorzugt!• BeliebigeTeileeinesFeldeskönnenübergebenwerden
– NichtunbedingtderAnfangdesFeldes• func(&a[2]);oderfunc(a+2);
– FüraufgerufeneFunktionistnichtsichtbar,dassaTeileinesgrößerenFeldesist
• KeineÜberprüfungdesIndexwertebereichesdurchdenCompiler– AndersalsPascal,Modula-2,Java,C#...– AuchnegativeIndizessinderlaubt
• Bspw.Infunc():charc=s[-2];
– Dennoch:ZugriffaufObjektaußerhalbFeldindexistillegal.ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 13
Adressarithmetik
• SeipeineZeigeraufeinFeldelement– p++;inkrementiertpaufdasnächsteFeldelement– p+=i;verschiebtZeigerumiFeldelemente
• SeienpundqZeigeraufdasselbeFeld– AdditionundSubtraktionsindfürZeigerzulässig:next10=p+10;– Vergleich:==,!=,<>=,etc.
• if(p>q)num_elem=q-p+1;/*ZahlderzwischenliegendenElemente*/
• ZeigersindkeineInteger– EinzigeAusnahme:Konstante0– Zeigerkönnenmit0verglichenwerden– 0istniemalseinegültigeAdresse– SymbolischeKonstanteNULL/*definiertinstdio.h*/
• ResultateundefiniertwennpundqnichtaufdasselbeFeldverweisen
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 14
Speicherverwaltung
• EinBeispielfüreineeinfacheHeap-Speicherverwaltung– VerwaltungineinemstatischenFeldallocbuf– alloc()undafree()müssen„passend“aufgerufenwerden
(StrukturierungalsStack)
– allocpmarkiertdenPunkt,biszudemSpeicherbenutztist• alloc()inkrementiertallocpundgibtaltenWertzurück• Afree()dekrementiertallocp
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
allocbuf:
allocbuf:
allocp
benutzt frei
frei
allocp
textstore.c
alloc.c
AndreasPolze 15
Speicherverwaltung(richtig)
• CLaufzeitsystembietetmehrereRoutinenzurVerwaltungdesHeaps#include<stdlib.h>voidfree(void*ptr);void*malloc(size_tsize);
• mallocfordertHeap-SpeichervomBetriebssysteman– Verwaltetfree-Liste– VergibtBlöckenach„firstfit“-Strategie
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
benutzt benutzt benutzt nichtmalloc benutzt
Freiblockliste
Speicherblocksizenext
Zeiger auf nächsten freien Block
Adresse, die malloc zurück-gibt
AndreasPolze 16
VerwendungvonHeapspeicher
• mallocundfreekönneninbeliebigerReihenfolgegerufenwerden– Vergessenefree-Operationenführenzu„Speicherlecks“– BetriebssystemgibtbeiTerminierungeinesProzessesallenSpeicherfrei
• GranularitätderSpeicherallokation– HäufigeAufrufevonmallocà großerOverhead
also:großeBlöckeverwenden– DasFindeneinesfreienBlocksistvieleinfacherbeikleinenBlöcken
also:kleineBlöckeverwenden– malloc()verwaltetSpeicherimuser-mode
à nurseltenBetriebssystemaufrufezumAusfassenvonSpeichernötig– malloc()undfree()sindnichtthread-sicher
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
textstore2.c
AndreasPolze 17
Zeigerarithmetik
• ZeigerundIntegerkönnenaddiert/subtrahiertwerden– p+nà dasn-teObjekthinterdem,aufdaspgegenwärtigzeigt– UnabhängigvomTypdesObjektesp
• nwirdentsprechendderGrößedesObjekttypsskaliert• ObjekttypwirdbeiDefinitionvonpfestgelegt• WärepvomTypechar*,sowürdebyteweiseinkrementiert
– WärepvomTypefloat*,sowürdep++aufdennächstenfloat-Wertweisen• Inkrementum4Byte
• GültigeOperationenfürZeiger– Zuweisung,Addition/SubtraktionvonZeigerundInteger– VergleichzweierZeigedieaufdasselbeFeldzeigen– ZuweisungvonNULL– VergleichmitNULL
• AlleZeigerkönnennachvoid*umgewandeltwerdenundumgekehrt
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 18
Zeichenkettenkonstantenvs.Felder
• Zeichenkettenkonstanten– char*pmessage=”nowisthetime”;– charamessage[]=”helloworld”;
– pmessage:Zeigerkanngeändertwerden,Zeichenkettenicht– amessage:Zeichenkettekannbeliebigmodifiziertwerden
amessage[0]=’H’;amessage[6]=’W’;
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
now is the time\0
hello world\0
pmessage:
amessage:
something different\0
AndreasPolze 19
Dereferenzierung
• Feldzugriffs-Operator([]}undZeiger-Dereferenzierung(*)lassensichinFunktionensynonymverwenden
/*strcpy:copyttos;arraysubscriptversion*/voidstrcpy1(char*s,char*t){
inti=0;while((s[i]=t[i])!='\0')
i++;}
/*strcpy:copyttos;pointerversion1*/voidstrcpy2(char*s,char*t){
while((*s=*t)!='\0'){s++;t++;
}}
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
strcpy.c
Vorteilstrcpy2:Funktioniertauchfürsehr
langeZeichenketten
(wennLängenichtmehrdurchintausgedrückt
werdenkann)
AndreasPolze 20
FeldervonZeigern
• ZeigersindVariablen• KönneninFelderngespeichertwerden
– Bsp:DerLängenachsortieren
– ZeigersindineinemFeldgespeichert– VertauschenderZeilendurchÄndernderZeiger– Speicherverwaltungbleibteinfach
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
abc
defgh
ijkl
lensort.c
AndreasPolze 21
MehrdimensionaleFelder
• Cbietetrechteckige,mehrdimensionaleFelder- Matrizen– intA[3][4];intB[3][4][5];– Indexbereich:jeweils0..n
– ZugriffaufFeldelemente:inti=A[1][2];
• AlleFeldelementehabendenselbenTyp– ZeilenweiseimSpeicherabgelegt– InitialisierungdurchWerteingeschweiftenKlammern
A={{1,2,3,4},{5,6,7,8},{9,10,11,12}}
• BeiDeklarationvonFunktionsparameternmussZahlderSpaltenangebenwerden– func(inta[][4]);besserfunc(inta[3][4]);– ErsteDimensionkannweggelassenwerden(...ÜbergebenwirdnochimmereinZeigerauferstesElement)
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
1 2 3 4
5 6 8
9 10 11 12
7
AndreasPolze 22
Zeigervs.MehrdimensionaleFelder
• MehrdimensionaleFelderbelegenstets(nxmxp...)vieleSpeicherzellen– intA[10][20]belegt200Zellená4byte=800byte– Alternative:int*B[10];
FeldvonZeigernaufFeldermit20Integern• Belegtinitialnur10Speicherzellená4byte(32bit)==40byte
– A[3][4]=B[5][6]à syntaktischäquivalenterZugriff• PassendeInitialisierungvonBvorausgesetzt
– ZeilenineinemZeiger-FeldkönnenunterschiedlicheLängehaben• EffizienteDatenstrukturen• „Löcher“
– FürZeichenkettenbietensichgenerellFeldervonZeigernan
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
AndreasPolze 23
Kommandozeilen
• C-LaufzeitumgebungenthältStandardmechanismusderParameterübergabe– intargcà ZahlderArgumente– char*argv[]à NULL-terminiertesFeldvonZeigernaufdieArgumente– Bsp:
echohello,world
– ErstesArgument:argv[0]à NamedesProgramms– OptionaleArgumente:argv[1]...argv[argc-1]– C-Standardverlangt:argv[argc]==NULL
• FeldvonZeigernaufZeichenketten– Kanngelesenundgeschriebenwerden
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
NULL
echo\0
hello,\0
world\0
argv:
lensort.c
AndreasPolze 24
ZeigeraufFunktionen
• FunktionenrepräsentierenSprüngeimCode– FunktionwirdrepräsentiertdurchAnfangsadresseeinesCodesegments– ZeigeraufFunktionenspeicherndieseAdresse
• Funktionszeigerkönnen– InVariablen,Feldernetc.gespeichertwerden– AlsFunktionsargumenteübergebenwerden– VonFunktionenzurückgegebenwerden
• Deklaration– <type>(*<name>)([<type>+]);– int(*compare)(char*,char*)=strcmp; /*strcmpwirdzugewiesen*/
• Aufruf– (*compare)(”hello”,”world”); /*strcmpwirdaufgerufen*/
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
strsort.c
AndreasPolze 25
KomplizierteDeklarationen• CSyntaxistmitunterverwirrend
• int*f(); /*f:eineFunktion,dieeinenZeigeraufintzurückgibt */• int(*pf)(); /*pf:ZeigeraufeineFunktion,dieintzurückgibt */
– Problem:• *istPräfix-Operator,hatniedrigerenVorrangals()• KlammersetzungistnötigumrichtigeAssoziationzuerzwingen
• Beispiele:char**argvint(*daytab)[13]int*daytab[13]void*comp()void(*comp)()char(*(*x())[])()
char(*(*x[3])())[5]
• Lösung:typedef– schrittweise,verständlicheTypdefinitionen(Unit10)ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1
à argv: Zeiger auf Zeiger auf char
à daytab: Zeiger auf Feld[13] von int
à daytab: Feld[13] von Zeigern auf intà comp: Funktion, die Zeiger auf void zurückgibtà comp: Zeiger auf Funktion, die void zurückgibtà x: Funktion, die einen Zeiger auf ein Feld[] von
Zeigern auf Funktionen die char zurückgeben, zurückgibt
à x: Feld[3] von Zeigern auf Funktionen, die einenZeiger auf ein Feld[5] von char zurückgeben
AndreasPolze 26
Zusammenfassung
• HeapundStack– ZweigetrennteSpeicherbereiche,LebensdauervonObjekten
• ZeigerundAdressen– ZeigerundFunktionen(-argumente)à call-by-valueemulieren– ZeigerundArraysà jedesFeldwirddurchZeigeraufAnfangdargestellt
• Adreßarithmetik– ErlaubtfürZeiger,dieaufdasgleichFeldverweisen– Beispiel:mallocundAlgorithmenzurSpeicherallokation
• MehrdimensionaleFelder– VariabelnurinersterDimension– InitialisierungvonFeldernà legtersteDimensionfest– BeiunvollständigerListevonInitialisierernbleibenEinträgeundefiniert
• Kommandzeilenbearbeitung– FeldmitVerweisenaufArgumenteundArgumentzahlvomLaufzeitsystembereitgestellt
• Funktionszeiger– Eleganter,flexiblerAnsatzumgenerischeProgrammezuschreiben– KomplizierteDeklarationen
ProgrammierspracheC- ZeigerundFelder,Programmiertechnik1