*Pekarvärden *Pekarvariabler & *
Motivering Pekare är ett fundamentalt koncept i C (och C++) Multipla returvärden från funktioner. Arrayer hanteras via pekare Dynamiskt minne (kommer i slutet av kursen) kräver pekare.
Vad är en pekare? Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista i datorn Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Kan lagras i pekarvariabler
Vad är en pekare? Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista i datorn Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Kan lagras i pekarvariabler Minnet Adresser 0 42 43 44 45 46 47
Vanliga variabler Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Först lite om vanliga variabler: Deklaration av en variabel gör att programmet när det kör reserverar tillräckligt med minne för den och sätter en etikett på denna låda int x; Minnet Adresser 0 42 43 44 45 46 47
Vanliga variabler Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Först lite om vanliga variabler: Deklaration av en variabel gör att programmet när det kör reserverar tillräckligt med minne för den och sätter en etikett på denna låda Tilldelning: värdet hamnar i lådan int x; x = 7; Minnet 7 Adresser 0 42 43 44 45 46 47
Vanliga variabler Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Först lite om vanliga variabler: Deklaration av en variabel gör att programmet när det kör reserverar tillräckligt med minne för den och sätter en etikett på denna låda Tilldelning: värdet hamnar i lådan När variabeln används kopieras värdet från lådan int x; x = 7; y = x + 4; Minnet 7 Adresser 0 42 43 44 45 46 47
Åter till pekare Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Kan lagras i pekarvariabler För att skapa ett pekarvärde kan man använda den unära operatorn &. Om man t.ex. skriver ett uttryck &x så får man adressen till x (som i detta fall råkar vara 42) int x; Minnet Adresser 0 42 43 44 45 46 47
Pekarvariabel Minnet kan lagra tal organiserat i 8-bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Kan lagras i pekarvariabler För att skapa ett pekarvärde kan man använda den unära operatorn &. Om man t.ex. skriver ett uttryck &x så får man adressen till x Tecknet * används för att deklarera en pekarvariabel int x; int *px; p Minnet Adresser 0 42 43 44 45 46 47 48
Pekarvariabel Minnet kan lagra tal organiserat i 8- bitarsgrupper (bytes) Alla bytes är organiserade i en lista Listan numreras från 0 och uppåt, kallas adresser eller pekarvärden Kan lagras i pekarvariabler För att skapa ett pekarvärde kan man använda den unära operatorn &. Om man t.ex. skriver ett uttryck &x så får man adressen till x Tecknet * används för att deklarera en pekarvariabel - som kan peka på saker: int x; int *px; px = &x; p Minnet Adresser 0 42 43 44 45 46 47 48
Utskrift Pekarvärden kan skrivas ut med printf med %p (i allmänhet inte så värdefullt, men kan vara till hjälp vid besvärlig felsökning). E #include <stdio.h> int main(void) { int x, y; int *p; // p är en pekare till int p = &x; // p sätts att peka på x printf( x finns på adressen %p\n, p); return 0; y: p:
Pekarvariabel Pekarvariabler kan användas för att indirekt komma åt värdet i de utpekade variablerna. E #include <stdio.h> int main(void) { y: int x, y; int *p; // p är en pekare till int p = &x; // p sätts att peka på x p: *p = 7; // Tilldelar det som p pekar på värdet 7 return 0; 7
Pekarvariabel Pekarvariabler kan användas för att indirekt komma åt värdet i de utpekade variablerna. E #include <stdio.h> int main(void) { y: int x, y; int *p; // p är en pekare till int p = &x; // p sätts att peka på x p: *p = 7; // Tilldelar det som p pekar på värdet 7 return 0; OBS! Samma tecken men betyder helt olika saker!! 7
Pekarvariabel Pekarvariabler kan användas för att indirekt komma åt värdet i de utpekade variablerna. E #include <stdio.h> int main(void) { y: int x, y; int *p; // p är en pekare till int p = &x; // p sätts att peka på x p: *p = 7; // Tilldelar det som p pekar på värdet 7 y = *p; // Tilldelar y det som p pekar på return 0; 7 7
I övrigt som vanligt Pekarvariabler Är i övrigt som vanliga variabler de kan tilldelas (pekarvärden) deras värden (pekarvärde) kan användas för att tilldela andra pekarvaribler. #include <stdio.h> int main(void) { int x, y, *a, *b; a = &x; // a sätts att peka på x b = &y; // b sätts att peka på y... a = b;// a sätts att peka på samma som b return 0; y: a: b:
I övrigt som vanligt Pekarvariabler Är i övrigt som vanliga variabler de kan tilldelas (pekarvärden) deras värden (pekarvärde) kan användas för att tilldela andra pekarvaribler. #include <stdio.h> int main(void) { int x, y, *a, *b; a = &x; // a sätts att peka på x b = &y; // b sätts att peka på y... a = b;// a sätts att peka på samma som b return 0; y: a: b: &x
I övrigt som vanligt Pekarvariabler Är i övrigt som vanliga variabler de kan tilldelas (pekarvärden) deras värden (pekarvärde) kan användas för att tilldela andra pekarvaribler. #include <stdio.h> int main(void) { int x, y, *a, *b; a = &x; // a sätts att peka på x b = &y; // b sätts att peka på y... a = b;// a sätts att peka på samma som b return 0; y: a: b: &x &y
I övrigt som vanligt Pekarvariabler Är i övrigt som vanliga variabler de kan tilldelas (pekarvärden) deras värden (pekarvärde) kan användas för att tilldela andra pekarvaribler. #include <stdio.h> int main(void) { int x, y, *a, *b; a = &x; // a sätts att peka på x b = &y; // b sätts att peka på y... a = b;// a sätts att peka på samma som b return 0; y: a: b: &y &y
Övning Koden på föregående sida finns på hemsidan som exempel 8. Lägg till kod (på lämpligt ställe) så att användaren kan skriva in värden som tas emot i variablerna x och y (genom att använda dessa). Skriv nu en tilldelningssats så att x får värdet av summan av de två talen men använd bara pekarvariablerna i tilldelningssatsen inte x eller y. Skriv ut följande både före och efter den sista pekartilldelningen: Värdena i x och y Värdena som pekas ut av a och b Värdena i a och b Ändra nu koden så att a och b används för inläsningen (alltså i den scanf-sats som du har skrivit).
Pekarvariabel och typ En pekarvariabel är begränsad till att kunna peka på en viss typ. Låter man den peka på en annan typ så blir det oftast fel när man kör programmet (kompilatorn varnar): #include <stdio.h> int main(void) { char c; int *y; y = &c; // Blir fel för y och &c har olika typ return 0;
Tillämpning En använding av pekare är som nämnts att returnera fler än ett värde från en funktion E skriv en funktion gör en frekvensanalys : Ta reda på vilket heltal som förekommer flest gånger i en array Håll reda på hur många gånger det förekom Både antalet gånger och vilket tal det är behöver komma anroparen tillgodo Anta att alla talen är små t.ex. mindre än 1000.
Multipla returvärden - fel int analyze_frequences(int arr[], int n) { /* Return the number that is most frequent in the array and the number of occurrences of that number */ return number, occurances; C har inte stöd för multipla int main(void) { returvärden int arr[100]={1,2,3,4,2,2,3; int number, occurances; number, occurances = analyze_frequences(arr, 7); printf( %d %d\n, number, occurances); return 0;
Multipla data returneras - pekare void analyze_frequences(int arr[], int n, int *number, int *occurances) { /* Find the number that is most frequent in the array and the number of occurrences of that number */ int main(void) { int arr[100]={1,2,3,4,2,2,3; int number, occurances; analyze_frequences(arr, 7); // Error! re write it correctly! printf( %d %d\n, number, occurances); return 0;
Övning Koden på förra sidan finns som exempel 9 på hemsidan. Rätta till anropet till funktionen analyze_frequences. Lägg till koden i funktionen analyze_frequences så att den löser sin uppgift (som indikeras av kommentaren).
Vanligt misstag int main(void) { Det är olämpligt att använda värdet av en vanlig variabel om den inte har getts något värde int x; printf( %d\n, x); // Värdet är odefinierat return 0; På samma sätt är det mycket olämplig att använda ett odefinierat pekarvärde int main(void) { int *q; int x; *q = 7; // Pekarvärdet är odefinierat! q = &x; return 0;
Summering Variabler kan vara av typen pekare En * i deklarationen bestämmer att de har typen pekare till någon typ char *v; // v är pekare till char En * intill en pekarvariabel i ett uttryck betyder det som pekarvariabeln pekar på Att tilldela en pekarvariabel utan * betyder att ändra dess pekarvärde (till att peka på något annat) Man skapar ett pekarvärde med &. &m betyder en perkare till m. Om m har typen t så har &m typen t*
Motivering Att kunna returnera fler än ett värde från en funktion Andra motiveringar blir klarare senare i kursen