Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  7 1324
Velkommen til "Yet another C guide" denne gangen skal vi se på pekere (pointers).
Som nevnt i tidligere guide når vi så på structs (strukturer) deklarerte vi en struktur peker med (*) tegnet som kalles peker.

En peker er en variabel som innholder adressen til en annen variabel.
Kort sitert fra boken "The C Programming Language" som anbefales,
<< Pointers are much used in C, partly because they are somtimes the only way to express a computation, and partly because they usually lead to more compact and efficient code than can be obtained in other ways.>>

Kode

int *a;
   int b;
   printf("Skriv et heltall:");
   b = atoi(gets(b));
   a = &b;
   printf("a innholder:%d \n",(*a));
   printf("minne adressen til a: %X \n", &a);
   printf("minne adressen a peker til: %X \n", a);
   printf("minne adressen til b: %X \n", &b);
Aller først så deklarer vi et heltallspeker *a;
og et heltall b;
Deretter ønsker vi at brukeren skal få muligheten å tilordne b en verdi.
b = atoi(gets(b)); gets funksjonen tilordner verdien b strengen som kommer fra konsollet.
Men siden det er heltall vi jobber med ønsker vi ikke strenger (char *), derfor kommer atoi funksjonen inn som konverterer strengen i b til heltall.
scanf kan også brukes til dette og vi skal se på det senere.
a = &b; her skjer det viktigste, heltallspekeren a peker nå på adressen til b ved hjelp av & operatoren.
printf("minne adressen a peker til: %X \n", a);
Og for å få adressen til selve pekeren trenger vi ikke & forran pekeren.

printf("a innholder:%d \n",(*a));
Her skriver vi ut verdien a peker på %d betyr skriv ut i heltallsformat, (*a) betyr verdien pekeren peker på.
med &a og &b skriver vi ut minne adressen til a og b, for å se hvilken adresse a peker på.
Vi bruker formatet %X som betyr skriv ut i hexadecimal format.

Kode

*a = 0;
printf("a er nå %d \n", (*a));
Nå som dere har forstått når man skal ha * forran variabelen og når man ikke skal,
kan dere tenke dere hva *a = 0; gjør?
Jo hadde vi isteden skrevet a = 0; så ville adressen til peker a blitt 0, og ikke selve verdien.

Kode

int *funksjonPeker (void);
Siden vi kan ha pekere til alle datatyper i C, kan vi også ha pekere til funksjoner/metoder.

Kode

int *funksjonPeker(void)
{
    int c;
    printf("skriv enda et heltall:");
    scanf("%d", &c);
    return c;  
}
Funksjonen vår gjør ikke mye annet enn å retunere heltall,
merk at jeg bruker scanf istedenfor gets.
Scanf gjør nesten det samme som gets, den tar input fra tastatur og legger verdien med riktig format i variabelen c.

Kode

*a = funksjonPeker();
printf("a er nå %d \n",(*a));
Og til slutt får vi bruk for funksjonen vår, vi har fortsatt heltallspekeren *a og
hvis dere husker riktig så betyr *a = funksjonsPeker(); verdien a peker på = verdien funksjonPeker retunerer.

Det var alt, kopier koden nedenfor og kjør lek med den og se hva som skjer, til de av dere som bruker GCC under Linux kommer dere til å bli skjent med feilmeldingen "Segmentationfault!" når deres peker ikke peker riktig og under Windows/DEV-CPP for dere error report vinduet opp

Kode

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int *funksjonPeker (void);

int main(int argc, char *argv[])
{
    
   int *a;
   int b;
   printf("Skriv et heltall:");
   b = atoi(gets(b));
   a = &b;
   printf("a innholder:%d \n",(*a));
   printf("minne adressen til a: %X \n", &a);
   printf("minne adressen a peker til: %X \n", a);
   printf("minne adressen til b: %X \n", &b);

   *a = 0;
   printf("a er nå %d \n", (*a));
   
   *a = funksjonPeker();
   printf("a er nå %d \n",(*a));
   
   system("PAUSE");	
   return 0;
}

int *funksjonPeker(void)
{
    int c;
    printf("skriv enda et heltall:");
    scanf("%d", &c);
    return c;  
}
Sist endret av bashrc; 6. august 2005 kl. 00:41.
Det de fleste nystartede programmerere ofte tenker er "Hvorfor bruke pekere?", noe som jeg tror gjør det vanskelig for en nybegynner å forstå peker-bruken. Så kan være kjekt å nevne litt hvorfor man bruker dem
Sånn da er guiden ferdig, kom litt for raskt borti send knappen istad.

Sitat av Kalakov
Det de fleste nystartede programmerere ofte tenker er "Hvorfor bruke pekere?", noe som jeg tror gjør det vanskelig for en nybegynner å forstå peker-bruken. Så kan være kjekt å nevne litt hvorfor man bruker dem
Vis hele sitatet...
Ja pekere er jo noe av det vanskeligste ved C språket, og er ikke lett å fatte med en gang for de fleste, var slik for meg i hvertfall inntil jeg leste en bra tutorial og med endel trening kan man forstå og se nytten av pekere.
▼ ... noen uker senere ... ▼
Akkuratt det Kalakov sa satt jeg å tenkte gjennom hele denne guiden din, og det samme har jeg tenkt hver gang jeg har prøvd lese litt c/c++ bøker når de tar for seg temaet pekere.. Masse om hvordan man bruker det, men har aldri skjønt hvorfor man skal bruke pekere når man f.eks skal lese data som ligger i en variabel, fremfor å bare lese det rett utifra variablen pekeren peker til...

Men jeg skal lese den tutorialen du linker til
bashrc's Avatar
Trådstarter
Jeg tror jeg har prøvd å svare på det kalakov spurte om, i hvertfall når jeg siterte
K&R's The C programming Language.

<< Pointers are much used in C, partly because they are somtimes the only way to express a computation, and partly because they usually lead to more compact and efficient code than can be obtained in other ways.>>
Vis hele sitatet...
Kort sagt til minnehåndtering for å yte effektivitet, derfor brukes pekere.

Dere får rette meg hvis det er feil!
Pekere brukes vel for det meste til å la funksjoner modifisere variablene de får som argumenter (uten at de trenger å være globale), og til dynamisk allokering av minne.

Eksempler:

Kode

. void foo(int *bar)
. {
.     *bar = 0;
. }
.
. int main()
. {
.     int n;
.     foo(&n); //setter n til 0
.
.     return(0);
. }

Kode

. //en array vil alltid ha et forhåndsbestemt antall elementer
. int foo[100];
.
. //dynamisk allokering (når du ikke vet hvor mye plass du trenger)
. int *bar;
. bar = malloc(size * sizeof(int));
Jeg anbefaler dere også å ta en titt på dette kapittelet: http://www.oreilly.com/catalog/pcp3/chapter/ch13.html
Det kan gjøre praktisk peker bruk litt lettere.
Hva om du skal lage en database liste over feks cd'ene dine?
Hvor mange har du? 20?
OK du lager et array på 20 elementer og skriver inn infoen om cd'ene dine der.

Også kjøper du en ny cd. Hmmm. rekompilere programmet med 21 elementer i arrayet.

Vel ikke særlig smart.

Hva med en lenket pekerliste. Der du har en peker som peker til det første elementet i listen. og en peker variabel i hver element som peker på neste element i listen.
Når du da kjøper en ny cd, så allokerer du bare plass til et nytt element og slenger det inn i listen.

Jada. Jeg vet at det er lurere å lagre slike data i en fil på disk, men eksempelet er fremdeles gyldig.

Pekere brukes primært til å allokere data dynamisk i et program.