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

Structs och funktionspekare

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

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

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

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

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

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

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

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

TDIU01 - Programmering i C++, grundkurs

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

Funktionspekare, inledning: funktionsanropsmekanismen. Anrop via pekare

Det finns många flaggor till g++,

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

Arrays (indicerade variabler) Föreläsning 6

Pekare och arrayer. Indexering och avreferering

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

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

Arrays (indicerade variabler) Föreläsning 4

*Pekarvärden *Pekarvariabler & *

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

Innehåll. Pekare Syntax

6.1 Kompilering och lite grundläggande information

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

TDDC76 - Programmering och Datastrukturer

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

Klassdeklaration. Metoddeklaration. Parameteröverföring

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

2 Pekare och dynamiska variabler.

Grundläggande C-programmering

Indexerade variabler

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

Poster ( structar ) Postdeklarationer

Tentamen med lösningsförslag

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

C++-programmets beståndsdelar

En kort text om programmering i C.

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

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

Innehåll. Pekare Exempel

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

4 Sammansatta datatyper

Maskinorienterad programmering

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

Indicerade variabler

Lathund. Pacific C för MS-DOS

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

Tommy Färnqvist, IDA, Linköpings universitet

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

LEU240 Mikrodatorsystem

PC-teknik, 5 p LABORATION ASSEMBLERINTRODUKTION

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

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

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

Funktioner och programstruktur. Föreläsning 5

Tentamen *:58/ID100V Programmering i C Exempel 3

Övning 3 i 2D1324. Strukturering h filer deklaration vs definition Debuggning gdb Preprocessorn #define assert(s) FILE LINE Länkning

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

Parameteröverföring. Exempel. Exempel. Metodkropp

Kontrollskrivning Mikrodatorteknik CDT S2-704

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

Heltal(int) Programmeringsteknik 54

Exempel ( )

Ett enkelt program i C++, hello.cpp. #include <iostream> int main() { std::cout << "Hello World\n"; return 0; } C++, Övning 1

Exempelsamling Assemblerprogrammering

TDIU01 - Programmering i C++, grundkurs

Programmering A. Johan Eliasson

Funktioner och programstruktur. Föreläsning 5

grundläggande C++, funktioner m.m.

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

översiktskurs (5DV031)

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Digital- och datorteknik

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

Digital- och datorteknik

Innehåll. Pekare Exempel

TDDC77 Objektorienterad Programmering

6 Lågnivåprogrammering

Classes och Interfaces, Objects och References, Initialization

Assemblerprogrammering för ARM del 2

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

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

F5: Högnivåprogrammering

Pekare ( )

F5: Högnivåprogrammering

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

Objektorienterad Programmering (TDDC77)

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 a 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 1. Pekarens värde är en adress (&). 2. Pekarens typ berättar hur man tolkar bitarna som finns på adressen. 3. * används för att läsa (dereferera) 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. 0x20030108... 0x20030108 3000 0x20030104 2000 0x20030100 1000 0x00000001 0x00000000 minlön lönenivå3 lönenivå2 lönenivå1 Ökande adresser 6

Pekare 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 unsigned char -1 255 7

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) 8

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

Pekare sammanfattning &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 (t ex till en annan variabel eller port) och a måste vara av typen pekare. *a hämtar värdet för den variabeln/porten. Exempel: char c = 'v'; char* p = &c; &p är0x2001c026 p är 0x2001bff3 *p är v Adress för c: Adress för p: 0x2001bff3 0x2001c026 p s värde 118 ('v')... 0x2001bff3... Dvs, om a s värde är en adress, så är *a vad adressen innehåller. *p är värdet som p pekar på, dvs 'v' Ökande adresser 10

Pekare ett till exempel char person1[] = "Elsa"; char person2[] = "Alice"; char person3[] = "Maja"; char* winner = &person2[0]; // == 0x20030200 typ värdet är en adress winner är 0x20030200 *winner är "Alice". 0x20030200... 0x20030202 i 0x20030201 l 0x20030200 A 0x00000001 0x00000000 winner "Alice" Ökande adresser 11

Pekare fler exempel 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 12

Pekare 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] 13

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å. 14

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 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 två pekare, pa respektive pb, 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] 1. Skapa två pekare, pa respektive pb, 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 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) Evalueras av preprocessorn till: INPORT_ADDR (port8ptr)inport_addr INPORT 0x40011000 (unsigned char*) 0x40011000 *((unsigned char*) 0x40011000) // läser från 0x40011000 value = INPORT; // läser från 0x40011000 value = *((unsigned char*) 0x40011000); 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 char * utport = (char*) 0x40011000; void f2() { *utport = 0; *utport = 1; *utport = 2; 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 - char* s1 = "Emilia"; - sizeof(s1) = 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 ej möjligt ty s2 endastsymbol 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 = s1 s värde = 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 symbol (ej variabel) för en adress som är känd i compile time. Eftersom s2 är en adress kan vi dereferera den precis som för en pekare: *s2 = E. 30

Indexering fler exempel #include <stdio.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. // b = "då"; // här försöker vi ändra b's värde, men det går inte via -syntax (C stödjer inte det). b[0] = 'd'; // OK b[1] = 'å'; // OK 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). 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 till en unsigned byte. 5. Vad gör volatile.

1. Skapa en port till en int 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 till en unsigned byte. 5. Vad gör volatile. [Övningsuppgifter] Svar: 1. 2. 3. 4. typedef volatile int* port8ptr; #defineport_addr 0x40004000 #define PORT *((port8ptr)port_addr); char *p = hej ; void fkn() { char s[] = hej ; // på stacken char* p = s; typedef unsigned char *byteptr; 5. Läsning/skrivning av volatile-variabel optimeras ej bort. Volatile därför nödvändigt för portar.

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