Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Relevanta dokument
Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

Programmering av inbyggda system. Pekare och Arrayer. Viktor Kämpe

Programmering av inbyggda system. Pekare och Arrayer. Ulf Assarsson. Originalslides av Viktor Kämpe

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Ulf Assarsson. Grundläggande C-programmering del 3. Läromoment: Grundläggande C-programmering del 3

Repetition C-programmering

Introduktion C-programmering

Assemblerprogrammering för ARM del 3

Föreläsning 10. Pekare (Pointers)

Att använda pekare i. C-kod

Ulf Assarsson. Grafisk display + seriekommunika3on (USART) Läromoment: USART Grundläggande C-programmering del 2

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Övning från förra gången: readword

Structs och funktionspekare

Pekare och Arrayer. Ulf Assarsson. Originalslides av Viktor Kämpe

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

TDIU01 - Programmering i C++, grundkurs

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Grundläggande C-programmering del 1 - För maskinorienterad programmering

Grundläggande C-programmering del 1 - För maskinorienterad programmering

Programmering i C++ EDA623 Typer. EDA623 (Föreläsning 4) HT / 33

#include <stdio.h> #include <string.h>

*Pekarvärden *Pekarvariabler & *

Grundläggande C-programmering del 4 Mer programstruktur samt Dynamisk minnesallokering Ulf Assarsson

Programmering, grundkurs, 8.0 hp HI1024, HI1900 etc., Tentamen TEN1. Måndagen den 10 januari 2011,

Programmeringsteknik för Ingenjörer VT06. Föreläsning 10

Pekare och arrayer. Indexering och avreferering

2 Pekare och dynamiska variabler.

Minnestilldelning (allokering) och frigörande (avallokering) av minne

Arrays (indicerade variabler) Föreläsning 6

Funktionspekare, inledning: funktionsanropsmekanismen. Anrop via pekare

Föreläsning 6 pekare och pekare tillsammans med arrayer

En kort text om programmering i C.

Arrays (indicerade variabler) Föreläsning 4

Det finns många flaggor till g++,

Hantering av textsträngar och talsträngar. William Sandqvist

TDDC76 - Programmering och Datastrukturer

6.1 Kompilering och lite grundläggande information

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Innehåll. Pekare Syntax

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Översikt Introduktion DST 1. Nicholas Wickström. IDE, Högskolan i Halmstad. N. Wickström

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Poster ( structar ) Postdeklarationer

Indexerade variabler

C++-programmets beståndsdelar

Byggstenar. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Grundläggande datatyper

Dynamiskt minne. Vad är dynamiskt minne Motivering Hur gör man i C Övningar

PC-teknik, 5 p LABORATION ASSEMBLERINTRODUKTION

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

2D1387, Programsystemkonstruktion med C++ Johnny Bigert, Kursens hemsida:

BMI = (vikt i kg) / (längd i m) 2. Lösningsförslag

4 Sammansatta datatyper

Grundläggande C-programmering

Innehåll. Pekare Exempel

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

Tentamen med lösningsförslag

Indicerade variabler

Tommy Färnqvist, IDA, Linköpings universitet

Klassdeklaration. Metoddeklaration. Parameteröverföring

LEU240 Mikrodatorsystem

Tentamen *:58/ID100V Programmering i C Exempel 3

struct egendefinierad typ struct LECTURE_TYPE { char teacher[99]; float lengthinminutes; char type; /* L = lecture, E = exercise */ };

Programmering i C++ EDA623 Mer om klasser. EDA623 (Föreläsning 6) HT / 26

Kapitel 1. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Kapitel 1 grunderna i C++

Elektroteknik MF1016 föreläsning 9 MF1017 föreläsning 7 Mikrodatorteknik

Enkla datatyper minne

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

HI1024, Programmering, grundkurs, 8hp KTH STH TENTAMEN. HI1024:TEN1 - Teoretisk tentamen Tid: Torsdagen den 20 oktober 2011,

Lathund. Pacific C för MS-DOS

Maskinorienterad programmering

TDIU01 - Programmering i C++, grundkurs

Funktioner och programstruktur. Föreläsning 5

Programmering, grundkurs, 8.0 hp HI1024, TEN1. Fredagen den 2 mars 2012

Programmering, grundkurs, 8.0 hp HI1024, omtentamen, TEN1. Tisdagen den 7 juni 2011,

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

C++ Lektion Tecken och teckenfält

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Digital- och datorteknik

6 Lågnivåprogrammering

Föreläsningsanteckningar, Introduktion till datavetenskap HT S4 Datastrukturer. Tobias Wrigstad

Kontrollskrivning Mikrodatorteknik CDT S2-704

Digital- och datorteknik

Objektorienterad Programmering (TDDC77)

Om pekare och minneshantering i C, relaterat till operativsystem och särskilt konstruktionen fork() execvp().

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

TDDC77 Objektorienterad Programmering

Inledande programmering med C# (1DV402) 27+15=42 1 (22)

Funktioner och programstruktur. Föreläsning 5

översiktskurs (5DV031)

Exempelsamling Assemblerprogrammering

Exempel ( )

IS1200 Datorteknik. Övning CE_O4 Maskinnära programmering med C Förberedelser till hemlaboration 1

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Vad har vi lärt oss så här långt Vad är en sträng? Strängkonstanter. Att skriva ut och läsa in strängar. Att arbeta med strängar.

Innehåll. 1 Funktionsmallar. 2 Pekare och konstanter. 3 Typomvandlingar. struct Name { string s; //... };

Föreläsning 12. struct

Transkript:

Grundläggande C-programmering del 2 Pekare och Arrayer Ulf Assarsson Läromoment: Pekare Absolutadressering (portar): typedef, volatile, #define Arrayer av pekare, arrayer av arrayer Hemuppgifter: v2.

Föregående lektion C-syntax Programstruktur, kompilering, länkning Bitoperationer se övningsuppgifterna 2

Pekare

Pekare A pointer is essentially a simple integer variable that holds a memory address of a value (variable or port), instead of holding the actual value itself. 4

Varför pekare? A pointer is essentially a simple integer variable that holds a memory address of a value (variable or port), instead of holding the actual value itself. Bland annat: Kunna referera till ett objekt eller variabel, dvs utan att behöva skapa en kopia Exempel 1: char person1[] = "Elsa"; char person2[] = "Alice"; char person3[] = "Maja"; char* winner = person2; Man kan säga att winner refererar till person2 men vi kallar det inte referens utan pekare. Dvs winner pekar på person2. Exempel 2: int lönenivå1 = 1000; int lönenivå2 = 2000; int lönenivå3 = 3000; int* minlön = &lönenivå3; minlön pekarpålönenivå3. 5

Pekare int lönenivå1 = 1000; int lönenivå2 = 2000; int lönenivå3 = 3000; int* minlön = &lönenivå3; 1. Pekarens värde är en adress (&). 2. Pekarens typ (int*) berättar hur man tolkar bitarna som finns på adressen. 3. * används även för att läsa (avrefferera) innehållet på adressen. int lönenivå1 = 1000; int lönenivå2 = 2000; int lönenivå3 = 3000; int* minlön = &lönenivå3; // == 0x20030108 typ värdet är en adress minlön är 0x20030108 *minlön är 3000. Exempel: printf( min lön = %i kr, *minlön); 0x20030108... 0x20030108 3000 0x20030104 2000 0x20030100 1000 0x00000001 0x00000000 min lön = 3000 kr minlön lönenivå3 lönenivå2 lönenivå1 Ökande adresser 6

Pekare Dvs, om a s värde är en adress, så är *a vad adressen innehåller. &a -> Adress till variabel a. Dvs minnesadress som a är lagrat i. a -> variabelns värde (t ex int, float eller en adress om a är pekarvaribel) *a -> Vad variabel a pekar på (här måste a's värde vara en giltig adress och a måste vara av typen pekare). a s värde är en adress till en annan variabel eller port. Vi hämtar värdet för den variabeln/porten. Exempel för pekarvariabel p: char c = 'v'; char* p = &c; Adress för c: 0x2001bff3 118 ('v')... *p är värdet som p pekar på, dvs 'v' Adress för p: 0x2001c026 0x2001bff3 p s värde... printf("%c = %c", c, *p); Utskrift: v = v Ökande adresser 7

Pekare char person1[] = "Elsa"; char person2[] = "Alice"; char person3[] = "Maja"; char* winner = person2; Minns: 1. Pekarens värde är en adress (&). 2. Pekarens typ (int*) berättar hur man tolkar bitarna som finns på adressen. 3. * används även för att läsa (avrefferera) innehållet på adressen. char person1[] = "Elsa"; char person2[] = "Alice"; char person3[] = "Maja"; char* winner = person2; // == 0x20030200 0x20030200... 0x20030202 i 0x20030201 l winner typ värdet är en adress 0x20030200 A "Alice" winner är 0x20030200 *winner är "Alice". Exempel: printf( winner is %s., winner); 0x00000001 0x00000000 Ökande adresser Winner is Alice. 8

Dereferera När vi derefererar en pekare så hämtar vi objektet som ligger på adressen. Antalet bytes vi läser beror på typen Tolkningen av bitarna beror på typen signed char 8 bitar 1111 1111 char str[] = "apa"; char* p = &str[0]; // = &(str[0]) char s = *p; unsigned char -1 255 char är ett 8-bits värde, dvs ett 8-bits tal. Ett tal kan motsvara en bokstav via ASCII-tabellen. 9

Pekare operatorer & * #include <stdio.h> int main() { char a, b, *p; a = 'v'; b = a; p = &a; Deklaration av pekare Adressen av... } printf("b = %c, p = 0x%p (%c) \n", b, p, *p); a = 'k'; printf("b = %c, p = 0x%p (%c) \n", b, p, *p); Dereferering Utskift: b = v, p = 0x0027F7C3 (v) b = v, p = 0x0027F7C3 (k) 10

Asterisken (*) betyder I deklarationer Pekartyp Som operator Dereferens ( av-referera ) char *p; char* p; void foo(int *pi); char a = *p; *p = 'b'; 11

C vs Assembler C Assembler Betyder intv; v:.space 4 skapa adressför v (t ex 4 bytes för integer) &v; LDR R0, =v v s adress (t ex 0x2001c010) v; LDR R0, v finns ej i thumb v s värde (t ex 5 eller 0x2001c004) LDR R0, =v LDR R0, [R0] *v; LDR R0, [v] finns ej i m4 värdet som ligger på v måste här vara pekare, LDR R0, =v adressen som ligger i v. t ex int *v; LDR R0, [R0] LDR R0, [R0] 12

Pekare - lathund t *p; p får typen pekare till typen t p = 0; p blir en tom pekare (pekar ej på något) p = &v; p tilldelas adressen till variabeln v *p betyder det som p pekar på p1 = p2; p1 kommer peka på samma som p2 *p1 = *p2; det som p1 pekar på kommer att ändras till det som p2 pekar på. 13

Mer varför pekare? Skriva till /Läsa från portar (Indexera fortare i arrayer) Slippa kopiera inputparametrar Ändra inputparametrarna #include <stdlib.h> #include <stdlib.h> void inc(int x, char y) { x++; y++; } void inc(int *x, char *y) { (*x)++; (*y)++; } Argumenten är pass-by value i C. int var1 = 2; char var2 = 7; inc(var1, var2); var1 och var 2 har fortfarande värdena 2 resp 7 efter funktionsanropet Argumenten är pass-by value i C. int var1 = 2; char var2 = 7; inc(&var1, &var2); var1 och var 2 har nu värdena 3 resp 8 efter funktionsanropet 14

Några pekarexempel int a[] = {2,3,4,10,8,9}; int *pa = &a[0]; short int b[] = {2,3,4,10,8,9}; short int *pb = b; float float c[] = {1.5f, 3.4f, 5.4f, 10.2f, 8.3f, 2.9f}; *pc = &c[3]; Pekare till sträng: char kurs[] = "Maskinorienterad Programmering"; char *pkurs = kurs; Vanlig skrivbar array på stacken eller i programmets datasegment. Eller direkt så här: char *pkurs = "Programmering av inbyggda system"; Men här lägger C-kompilatorn strängen i skrivskyddat strängliteralminne i programmetsdatasegment 15

Aritmetik på pekare char *kurs = "Maskinorienterad Programmering"; *kurs; *(kurs+2); kurs++; kurs +=4; // 'M // 's // kurs pekar på 'a // kurs pekar på 'n' Man ökar p med (n * typstorlek) int a[] = {2,3,4,10,8,9}; int *p = a; // == &(a[0]) p++; // p == &(a[1]) int *p3 = a + 3; 16

[Övningsuppgifter] 1. Skapa varsin pekare till int a = 5; char b = s ; 2. Ändra a och b s värden via pekarna. 3. Gör en funktion som modifierar en variabel, te x adderar 5: void add5( ) { } int a; add5( ); // ska öka a med 5

[Övningsuppgifter] Svar: 1. int *pa = &a; char *pb = &b; 2. *pa = 10; *pb = t ; 3. void add5(int* p) { *p += 5; } int a; add5( &a );

Pekare för Absolutadressering

Absolutadressering Vid portadressering så kan vi ha en absolut adress (t ex 0x40011004). 20

Absolutadressering 0x40011000 // ett hexadecimalt tal (unsigned char*) 0x40011000 // en unsigned char pekare som pekar på adress 0x40011004 *((unsigned char*) 0x40011000) // dereferens av pekaren // läser från 0x40011000 unsigned char value = *((unsigned char*) 0x40011000); // skriver till 0x40011004 *((unsigned char*) 0x40011004) = value; Men vi måste lägga till volatile om vi har på optimeringsflaggor...! 21

Läsbarhet med typedef typedef unsigned char* port8ptr; #define INPORT_ADDR 0x40011000 #define INPORT *((port8ptr)inport_addr) 0x40011000 (unsigned char*) 0x40011000 *((unsigned char*) 0x40011000) INPORT_ADDR (port8ptr)inport_addr INPORT // läser från 0x40011000 value = *((unsigned char*) 0x40011000); // läser från 0x40011000 value = INPORT; typedef förenklar/förkortar uttryck, vilket kan öka läsbarheten. typedef unsigned char* port8ptr; typ alias/typnamn 22

Volatile qualifier char * inport = (char*) 0x40011000; void foo(){ } while(*inport!= 0) { //... } En kompilator som optimerar kanske bara läser en gång (eller inte alls om vi aldrig skriver till adressen från programmet). 23

Volatile qualifier volatile char * inport = (char*) 0x40011000; void foo(){ } while(*inport!= 0) { //... } volatile hindrar vissa optimeringar (vilket är bra och här nödvändigt!), ty anger att kompilatorn måste anta att innehållet på adressen kan ändras utifrån. Vårt tidigare exempel, nu korrekt med volatile: unsigned char value = *((volatile unsigned char*) 0x40011000); // läser från 0x40011004 *((volatile unsigned char*) 0x40011004) = value; // skriver till 0x40011004 24

Sammanfattning portar Inport: typedef volatile unsigned char* port8ptr; #define INPORT_ADDR 0x40011000 #define INPORT *((port8ptr)inport_addr) Utport: typedef volatile unsigned char* port8ptr; #define UTPORT_ADDR 0x40011004 #define UTPORT *((port8ptr)utport_addr) // läser från 0x40011000 value = INPORT; // skriver till 0x40011004 UTPORT = value; 25

Pekare och Arrayer

Antal bytes med sizeof() #include <stdio.h> char* s1 = "Emilia"; char s2[] = "Emilia"; int main() { printf("sizeof(char): %i \n", sizeof(char) ); printf("sizeof(char*): %i \n", sizeof(char*) ); printf("sizeof(s1): %i \n", sizeof(s1) ); printf("sizeof(s2): %i \n", sizeof(s2) ); } return 0; sizeof(char): sizeof(char*): sizeof(s1): sizeof(s2): 1 4 4 7 Sizeof utvärderas i compile-time. En (av få) undantag där arrayer och pekare är olika. 27

Indexering samma för array/pekare #include <stdio.h> char* s1 = "Emilia"; char s2[] = "Emilia"; int main() { // tre ekvivalenta sätt att dereferera en pekare printf("'l' i Emilia (version 1): %c \n", *(s1+3) ); printf("'l' i Emilia (version 2): %c \n", s1[3] ); printf("'l' i Emilia (version 3): %c \n", 3[s1] ); // tre ekvivalenta sätt att indexera en array printf("'l' i Emilia (version 1): %c \n", *(s2+3) ); printf("'l' i Emilia (version 2): %c \n", s2[3] ); printf("'l' i Emilia (version 3): %c \n", 3[s2] ); } return 0; x[y] översätts till *(x+y) och är alltså ett sätt att dereferera en pekare. Indexering är samma för pekare som för array. Så är arrayer pekare? Nej 28

Array Likhet/olikhet med pekare char* s1 = "Emilia"; char s2[] = "Emilia"; Båda har en adress och en typ. char s2[] = "Emilia"; - sizeof(s2) == 7 - Men sizeof(char*) == 4; Indexering har samma resultat. s1[0] == E ; s2[0] == E ; *s1 == E ; *s2 == E ; // eftersom s2 är adress så kan vi dereferera den // precis som för en pekare 29

Array Likhet/olikhet med pekare char* s1 = "Emilia"; char s2[] = "Emilia"; s2 Typ: Array Pekarvariabel Adressering: Pekararitmetik: s2 = symbol = arrayensstartadress. s2 = &(s2[0]) s2[0] = *s2 = 'E' s2++ ej möjligt (s2+1)[0] helt OK s1 &s1 = adress för variabeln s1. s1 = värdet = strängens startadress. s1 = &(s1[0]) s1[0] = *s1 = 'E' s1++ heltok (s1+1)[0] helt OK Typstorlek: sizeof(s2) == 7 bytes sizeof(s1) == sizeof(char*) == 4 bytes s2 är endast symbol (ej variabel.) för adress som är känd i compile time. Eftersom s2 är adress så kan vi dereferera den precis som för en pekare: *s2 == E 30

Indexering fler exempel #include <stdio.h> #include <conio.h> char * s1 = "Emilia"; // s1 är pekare. Variabeln s1 är en variabel som går att ändra, och vid start tilldelas värdet av adressen till 'E : char s2[] = "Emilia"; // s2 är array. Värdet på symbolen s2 är känt vid compile time. // Symbolen s2 är konstant, dvs ingen variabel som går att ändra. // s2 är adressen till 'E. int main() { // tre ekvivalenta sätt att dereferera en pekare printf("'l' i Emilia (version 1): %c \n", *(s1+3) ); printf("'l' i Emilia (version 2): %c \n", s1[3] ); printf("'l' i Emilia (version 3): %c \n", 3[s1] ); printf("'l' i Emilia (version 3): %c \n", *(s2+3) ); printf("'l' i Emilia (version 3): %c \n", (s2+3)[0] ); char a[] = "hej"; (a+1)[0] = 'o'; char* p = a; p = "bye"; // funkar. Strängen bye" allokeras i compile time i strängliteralminne. char b[10] = "hej"; // b blir 10 element stor och får adressvärde // b = "då"; // här försöker vi ändra b's värde och det GÅR inte. } return 0; 31

Arrayer som funktionsargument blir pekare void foo(int i[]); void foo(int *i); [ ] notationen finns, men betyder pekare! Undviker att hela arrayen kopieras. Längd inte alltid känd i compile time. Adressen till arrayen läggs på stacken och accessas via stackvariabeln i. (En struct kopieras och läggs på stacken). Exempel: int sumelements(int *a, int l) { int sum = 0; for (int i=0; i<l; i++) { sum += a[i]; } return sum; } int array[] = {5,4,3,2,1}; sumelements(array, 5); 32

Array av pekare #include <stdio.h> char *fleranamn[] = {"Emil", "Emilia", "Droopy"}; int main() { printf("%s, %s, %s\n", fleranamn[2], fleranamn[1], fleranamn[0]); } return 0; Droopy, Emilia, Emil sizeof(fleranamn) = 12; // 3*sizeof(char*) = 3*4 = 12 33

Array av arrayer #include <stdio.h> char kortanamn[][4] = {"Tor", "Ulf", "Per"}; int main() { printf("%s, %s, %s\n", kortanamn[2], kortanamn[1], kortanamn[0]); } return 0; Per, Ulf, Tor sizeof(kortanamn) = 34

Array av arrayer #include <stdio.h> int arrayofarrays[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; int main() { int i,j; for( i=0; i<3; i++) { printf("arrayofarray[%i] = ", i); } for ( j=0; j<4; j++) printf("%i ", arrayofarrays[i][j]); printf("\n"); } return 0; 35

[Övningsuppgifter] 1. Skapa en port till en char som ligger på adress 0x40004000. 2. Skapa en pekare till en sträng som ligger i skrivskyddat strängliteralminne i datasegmentet. 3. Skapa en pekare till en sträng som ligger på stacken. 4. Använd typedef för att skapa ett typalias byteptr. 5. Vad gör volatile.

[Övningsuppgifter] Svar: 1. #define PORT *((volatile char*)0x40004000); 2. char *p = hej ; 3. char s[] = hej ; char *p = s; 4. typedef unsigned char *byteptr; 5. Läsning/skrivning av volatile-variabel optimeras ej bort.

Nästa föreläsning: Structs, funktionspekare