U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Ähnliche Dokumente
F Zeiger, Felder und Strukturen in C

Makros sind Textersetzungen, welche vom Präprozessor aufgelöst werden. Dies Passiert bevor der Compiler die Datein verarbeitet.

U5-2 Register beim AVR-µC

Übungen zu Systemnahe Programmierung in C (SPiC)

GdI2 - Systemnahe Programmierung in C Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2006 U4.fm

Wer möchte, kann sein Programm auch auf echter Hardware testen

F Zeiger, Felder und Strukturen in C

E Mikrocontroller-Programmierung

Übungen zu Systemnahe Programmierung in C (SPiC)

2. Programmierung in C

Inhalt. Aufgabe 4: LED-Modul Hinweise Testen des Moduls Sommersemester 2015

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Globale Variablen

Zeiger (engl. Pointer)

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

C- Kurs 08 Zeiger. Dipl.- Inf. Jörn Hoffmann leipzig.de. Universität Leipzig Ins?tut für Informa?k Technische Informa?

Teil 5: Zeiger, Felder, Zeichenketten Gliederung

Betriebssysteme, Rechnernetze und verteilte Systeme 1. Crashkurs C (2)

Programmierung mit C Zeiger

Übersicht. Speichertypen. Speicherverwaltung und -nutzung. Programmieren in C

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

Pointer und Arrays. INE1, Montag M. Thaler, Office TG208. ZHAW, M. Thaler, K. Rege, G.

6. Zeiger Allgemeines Definition eines Zeigers

Deklarationen in C. Prof. Dr. Margarita Esponda

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

8. Referenzen und Zeiger

Zeiger: Der Adressoperator &

Systemnahe Programmierung in C Übungen Moritz Strübe, Michael Stilkerich Universität Erlangen-Nürnberg Informatik 4, 2010 U2.fm

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Zeiger in C und C++ Zeiger in Java und C/C++

Programmieren in C. Speicher anfordern, Unions und Bitfelder. Prof. Dr. Nikolaus Wulff

C-Programmierung: Ausdrücke und Operatoren#Division.2F

C/C++-Programmierung

Dynamische Speicherverwaltung

Einführung in die Programmiersprache C

Vektoren 105. array-qualifier static restrict const volatile array-size-expression assignment-expression * simple-declarator identifier

Microcontroller Kurs Programmieren Microcontroller Kurs/Johannes Fuchs 1

Vorlesung Programmieren

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

Globale Variablen Diverses. Globale Variablen. Globale Variablen

Das folgende Programm demonstriert, wie man Speicheradressen von Variablen ermittelt.

Software Entwicklung 1

Crashkurs C++ - Teil 1

Parallel-IO. Ports am ATmega128

Inhalt. 1 Einstieg in die Welt von C Erste Schritte in C 31. Vorwort... 15

Zeiger in C und C++ Zeiger in Java und C/C++

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Arrays 115. array-qualifier static restrict const volatile array-size-expression assignment-expression * simple-declarator identifier

Programmiertechnik 1. Unit 9: Programmiersprache C Zeiger und Felder. Andreas Polze 1

einlesen n > 0? Ausgabe Negative Zahl

Zeiger, Arrays und Strings in C und C++

Variablen. Deklaration: «Datentyp» «Variablenname» Datentyp bestimmt Größe in Bytes: sizeof Beispiel: long int v; Größe: 4 Bytes

Grundlagen der Informatik 11. Zeiger

Arrays 120. array-qualifier static restrict const volatile array-size-expression assignment-expression * simple-declarator identifier

Propädeutikum. Dipl.-Inf. Frank Güttler

Einführung in die Programmierung II. 5. Zeiger

Dynamische Speicherverwaltung

Speicherklassen (1) Lokale Variablen

Datei: svn/ckurs/trunk/c_texte/c_arrptr.txt, Datum: 30. Juni Felder und Zeiger

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

Zusammenfassung des Handzettels für Programmieren in C

4.2 Programmiersprache C

Bereits behandelt: Einfache Datentypen / Variablen. Schleifen und Verzweigungen. Funktionen. Heute: Felder, Zeiger, Referenzen. Freispeicherverwaltung

Grundlagen der Informatik 2. Operatoren

Programmierkurs C++ Datenstrukturen Seite 1

7 Funktionen. 7.1 Definition. Prototyp-Syntax: {Speicherklasse} {Typ} Name ({formale Parameter});

Zeiger. C-Kurs 2012, 2. Vorlesung. Tino Kutschbach 10.

Bereits behandelt: Einfache Datentypen / Variablen. Schleifen und Verzweigungen. Funktionen. Heute: Felder, Zeiger, Referenzen. Freispeicherverwaltung

Betriebssysteme. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Betriebssysteme. Agenda. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Die Sprache C# Datentypen, Speicherverwaltung Grundelemente der Sprache. Dr. Beatrice Amrhein

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Organisatorisches. Übungsleiter: Karsten Otto Homepage: Aufgaben

U4-1 Aufgabe 3: einfache malloc-implementierung

6 ZEIGER UND REFERENZEN - ALLGEMEINES

Felder (1) Allgemeines

Algorithmen und Datenstrukturen

Arrays (Felder/Vektoren)

Variablen in C++ Einfache Variablen Strukturen Arrays und Zeichenketten Zeiger und Referenzen Parameter Dynamische Speicherverwaltung

C- Kurs 07 Höhere Datentypen

Programmieren in C. Zeiger auf void und ihre Anwendungen. Prof. Dr. Nikolaus Wulff

Angewandte Mathematik und Programmierung

Die Programmiersprache C. 3. Zeiger, Adressarithmetik

Programmierkurs C++ Variablen und Datentypen

Physische Datenstrukturen

INE1 Speicherverwaltung und zweidimensionale Arrays. Speicherorganisation Dynamischer Speicher in C Zweidimensionale Arrays

Advanced Programming in C

F Zeiger, Felder und Strukturen in C

Arrays,Strings&Pointer in C/C++

AVR Ein/Ausgabe. Inhaltsverzeichnis

Pointer. Variablen. Pointer. Ein elementares Beispiel. Pointer in C

Strukturen in C. Strukturen stellen eine Zusammenfassung von Datenelementen unterschiedlichen Typs unter einem Namen dar.

Übersicht. Informatik 1 Teil 9: komplexe Datentypen (Strukturen, Enumerationen, Unions)

Die Sprache C# Datentypen, Speicherverwaltung Grundelemente der Sprache. Dr. Beatrice Amrhein

Vorkurs C++ Programmierung

C-Pointer (Zeiger, Adressen) vs. C++ Referenzen

9. Vektoren. (auch Felder/array)

Ansteuerung eines LCD-Screens

Software Entwicklung 1. Rekursion. Beispiel: Fibonacci-Folge I. Motivation. Annette Bieniusa / Arnd Poetzsch-Heffter

Typ : void* aktuelle Parameter Pointer von beliebigem Typ

Eine praktische Einführung in die Programmierung mit der Programmiersprache C

Transkript:

U3 3. Übung U3 3. Übung Besprechung Aufgabe 1 Pointer Register und Ports U3.1 U3-1 Zeiger U3-1 Zeiger 1 Einordnung Konstante: a 0110 0001 Variable: a Zeiger-Variable (Pointer): a char *p = &a; p U3.2

2 Definition von Zeigervariablen U3-1 Zeiger Syntax: Typ *Name ; 3 Adressoperatoren Adressoperator &. &x Referenz Verweisoperator *. *x Dereferenzierung U3.3 4 Beispiele U3-1 Zeiger int x = 5; x 5 int *ip; int y; ip = &x; ip y 5 y = *ip; U3.4

5 Zeiger als Funktionsargumente (2) U3-1 Zeiger Beispiel: void swap (int *, int *); main(void) { int a, b;... swap(&a, &b); } a b void swap (int *px, int *py) { int tmp; px py ➍ tmp = *px; *px = *py; *py = tmp; ➍ tmp } U3.5 U3-2 Felder U3-2 Felder 1 Eindimensionale Felder Gleicher Typ Anzahl kann nicht mehr geändert werden der Zugriff durch Index, beginnend bei Null Definition eines Feldes Typ Name [ konstanter Ausdruck ] Initialisierung ; Beispiele: int x[5]; double f[20]; U3.6

2 Initialisierung eines Feldes U3-2 Felder, = { konstanter Ausdruck } Beispiel int prim[4] = {2, 3, 5, 7}; char name[5] = { O, t, t, o, \0 }; Nicht initialisierte Elemente werden mit 0 initialisiert. Automatische Größe int prim[] = {2, 3, 5, 7}; char name[] = { O, t, t, o, \0 }; char: Initialisierung durch Strings. char name1[5] = "Otto"; // { O, t, t, o, \0 }; char name2[] = "Otto"; U3.7 3 Zugriffe auf Feldelemente U3-2 Felder ' Indizierung: wobei: 0 <= Wert(Ausdruck) < Feldgröße Beispiele: Feldname [ Ausdruck ] prim[0] == 2 prim[1] == 3 name[1] == t name[4] == \0 Beispiel Vektoraddition: float v1[4], v2[4], sum[4]; int i;... for ( i=0; i < 4; i++ ) sum[i] = v1[i] + v2[i]; for ( i=0; i < 4; i++ ) printf("sum[%d] = %f\n", i, sum[i]); U3.8

U3-3 Zeiger und Felder U3-3 Zeiger und Felder Variable zeigt immer auf das erste Feld Wert kann nicht geändert werden es gilt: int array[5]; array int *ip = array; int *ep; ep = &array[0]; 1 ➍ ep = &array[2]; *ep = 1; ➍ ip ep U3.9 1 Arithmetik mit Adressen U3-3 Zeiger und Felder ++ -Operator: Inkrement = nächstes Objekt int array[3]; int *ip = array; array ip++; ip++; ip -Operator: Dekrement = vorheriges Objekt +, Größe des Objekttyps berücksichtigt! int array[5]; ip = array; ip = ip+3; ip U3.10

2 Vorrangregeln bei Operatoren U3-3 Zeiger und Felder Operatorklasse Operatoren Assoziativität primär ( ) Funktionsaufruf von links nach rechts [ ] unär! ~ ++ -- + * & von rechts nach links multiplikativ * / % von links nach rechts 3 Beispiele int a, i, *ip; i = 1; ip = &i; a = *ip++; (1) a = *ip++; (2) a = *ip++; a i ip? 1??? 1 U3.11 3 Beispiele (2) U3-3 Zeiger und Felder int a, i, *ip; i = 1; ip = &i; a = ++*ip; (1) a = ++*ip; *ip ++ (2) a = ++*ip; *ip a i ip? 2 1 2 int a, i, *ip; i = 1; ip = &i; a = (*ip)++; (1) a = (*ip)++; (2) a = (*ip)++; *ip ➍++ *ip a i ip 1? ➍ 1 2 U3.12

4 Zeigerarithmetik und Felder U3-3 Zeiger und Felder Ein Feldname ist eine Konstante, für die Adresse des Feldanfangs Feldname ist ein ganz normaler Zeiger Operatoren für Zeiger anwendbar ( *, [] ) aber keine Variable keine Modifikationen erlaubt es gilt: keine Zuweisung, kein ++, --, +=, int array[5]; /* array ist Konstante für den Wert &array[0] */ int *ip = array;/* int *ip = &array[0] */ int *ep; /* Folgende Zuweisungen sind äquivalent */ array[i] = 1; ip[i] = 1; *(ip+i) = 1; /* Vorrang! */ *(array+i) = 1; ep = &array[i]; *ep = 1; ep = array+i; *ep = 1; U3.13 4 Zeigerarithmetik und Felder U3-3 Zeiger und Felder int array[5]; int *pointer; char buffer[6]; char *bptr; array 10 920 array[0] = 10; array[1] = 920; strcpy(buffer,"hallo"); ➍ pointer = array; ➎ bptr = buffer; pointer ➍ ➍ Fomale Parameter der Funktion strcpy ziel quelle buffer bptr ➎ "hallo" h a l l o \0 ➎ h a l l o \0 U3.14

4 Zeigerarithmetik und Felder U3-3 Zeiger und Felder int array[5]; int *pointer; char buffer[6]; char *bptr; array ➒ 10 920 ➑ 700 array[0] = 10; array[1] = 920; strcpy(buffer,"hallo"); ➍ pointer = array; ➎ bptr = buffer; ➏ pointer++; ➐ bptr++; ➑ *pointer = 700; ➒ array++; pointer buffer bptr ➏ ➐ ➏ ➐ h a l l o \0 U3.15 5 Vergleichsoperatoren und Adressen U3-3 Zeiger und Felder Vergleich von Zeigern < kleiner <= kleiner gleich > größer >= größer gleich == gleich!= ungleich U3.16

U3-4 Eindimensionale Felder als Funktionsparameter U3-4 Eindimensionale Felder als Funktionsparameter ganze Felder können in C nicht by-value übergeben werden Verwendung von Zeigern bei der Deklaration des formalen Parameters wird die Feldgröße weggelassen Größe "bekannt" ggf. Größe mit einem extra Parameter übergeben Strings enden mit \0 U3.17 U3-4 Eindimensionale Felder als Funktionsparameter U3-4 Eindimensionale Felder als Funktionsparameter (2) Beispiel: int func(int p1, int p2[], int p3); oder: int func(int p1, int *p2, int p3); int a, b; int feld[20]; func(a, feld, b); die Parameter-Deklarationen int p2[] und int *p2 sind vollkommen äquivalent! U3.18

U3-5 Dynamische Speicherverwaltung U3-5 Dynamische Speicherverwaltung Feldgröße nicht änderbar Lösung: malloc() Zeiger auf den Anfang des Speicherbereichs Zeiger kann danach wie ein Feld verwendet werden ( []-Operator) void *malloc(size_t size) int *feld; cast-operator int groesse;... feld = (int *) malloc(groesse * sizeof(int)); if (feld == NULL) { perror("malloc feld"); exit(1); } for (i=0; i<groesse; i++) { feld[i] = 8; }... sizeof-operator U3.19 U3-5 Dynamische Speicherverwaltung U3-5 Dynamische Speicherverwaltung (2) Speicher muss wieder frei gegeben werden void free(void *ptr) double *dfeld; int groesse;... dfeld = (double *) malloc(groesse * sizeof(double));... free(dfeld); U3.20

U3-6 Explizite Typumwandlung Cast-Operator U3-6 Explizite Typumwandlung Cast-Operator C kann automatisch umwandeln (vgl. Abschnitt D.5.10) Beispiel: int i = 5; float f = 0.2; double d; d = i * f; float double Aber nicht immer (so wie man will) Syntax: Beispiel: (Typ) Variable Beispiele: (int) a (float) b feld = (int *) malloc(groesse * sizeof(int)); (int *) a (char *) a malloc liefert Ergebnis vom Typ (void *) cast-operator macht daraus den Typ (int *) U3.21 U3-7 sizeof-operator U3-7 sizeof-operator Bestimmung der Größe einer Variablen / Stuktur Syntax: sizeof x sizeof (Typ) liefert die Größe des Objekts x in Bytes liefert die Größe eines Objekts vom Typ Typ in Bytes Das Ergebnis ist vom Typ size_t ( int) (#include <stddef.h>!) Beispiel: int a; size_t b; b = sizeof a; /* b = 2 oder b = 4 */ b = sizeof(double) /* b = 8 */ U3.22

U3-8 Zeiger auf Zeiger U3-8 Zeiger auf Zeiger ein Zeiger kann auf eine Variable verweisen, die ihrerseits ein Zeiger ist int x = 5; int *ip = &x; int **ipp = &ip; /* ** ipp = 5 */ x 5 ip ipp U3.23 U3-9 Felder von Zeigern U3-9 Felder von Zeigern Auch von Zeigern können Felder gebildet werden Deklaration int *pfeld[5]; int i = 1 int j; Zugriffe auf einen Zeiger des Feldes pfeld[3] = &i; Zugriffe auf das Objekt, auf das ein Zeiger des Feldes verweist j = *pfeld[3]; ➍ ➍ pfeld pfeld[3] * pfeld[3] i 1 ➍ j U3.24

U3-10 Zeiger auf Funktionen U3-10 Zeiger auf Funktionen Datentyp: Zeiger auf Funktion Variablendef.: <Rückgabetyp> (*<Variablenname>)(<Parameter>); int (*fptr)(int, char*); int test1(int a, char *s) { return printf("1: %d %s\n", a, s); } int test2(int a, char *s) { return printf("2: %s %d\n", s, a); } fptr = test1; fptr(42,"hallo"); // "1: 42 hallo\n" fptr = test2; fptr(42,"hallo"); // "2: hallo 42\n" U3.25 U3-11 Register beim AVR- C Register beim AVR-mC Beim AVR- C sind die Register in den Speicher eingebettet am Anfang des Adressbereichs angeordnet Adressen sind der Dokumentation zu entnehmen vollständige Dokumentation für "unseren" Mikrokontroller ATMega32: http://www4.informatik.uni-erlangen.de/lehre/ws09/v_spic/uebung/doc/mega32.pdf Für die Aufgaben benötigte Register sind auf den Folien erwähnt Die Bibliothek (avr-libc), die wir verwenden, definiert bereits sinnvolle Makros für alle Register des AVR C (#include <avr/io.h>) U3.26

1 Funktionsweise von Registern U3-11 Register beim AVR-mC Register sind über den Daten-Bus angebunden Jedes Register hat eine vorgegebene Speicheradresse. Es kann wir "normaler" Speicher gelesen und geschrieben werden U3.27 2 Makros für Register-Zugriffe U3-11 Register beim AVR-mC Makros mit aussagekräftigen Namen können den Umgang mit Registern deutlich vereinfachen Beispiel: Makro für Register an Adresse 0x3b (PORTA beim ATmega32): #define PORTA (*(volatile uint8_t *)0x3b) Verwenden dieses Registers: volatile uint8_t *portptr = &PORTA; PORTA = 0; /* schreibender Zugriff */... if (PORTA == 0x04) /* lesender Zugriff */ PORTA &= ~4; /* lesender und schreibender Zugriff */ *portptr = 1; /* Zugriff über Zeiger */ Das volatile-schlüsselwort wird später erläutert, im Moment ist es bei sämtlichen Zugriffen auf Hardwareregister zu verwenden. U3.28

U3-12 I/O-Ports des AVR- C U3-12 I/O-Ports des AVR-mC Jeder I/O-Port des AVR- C wird durch drei 8-bit Register gesteuert: Datenrichtungsregister (DDRx = data direction register) Datenregister (PORTx) Port Eingabe Register (PINx = port input register, nur-lesbar) Jedem Anschluss-Pin ist ein Bit in jedem der 3 Register zugeordnet Beispiel: DDR von Port A: 7 0 DDRA PA7 bis PA0 AVR C U3.29 1 I/O-Port-Register U3-12 I/O-Ports des AVR-mC DDRx: hier konfiguriert man einen Pin i von Port x als Ein- oder Ausgang Bit i = 1 Pin i als Ausgang verwenden Bit i = 0 Pin i als Eingang verwenden PORTx: Auswirkung abhängig von DDRx: ist Pin i als Ausgang konfiguriert, so steuert Bit i im PORTx Register ob am Pin i ein high- oder ein low-pegel erzeugt werden soll Bit i = 1 high-pegel an Pin i Bit i = 0 low-pegel an Pin i ist Pin i als Eingang konfiguriert, so kann man einen internen pull-up- Widerstand aktivieren Bit i = 1 pull-up-widerstand an Pin i (Pegel wird auf high gezogen) Bit i = 0 Pin i als tri-state konfiguriert PINx: Bit i gibt den aktuellen Wert des Pin i von Port x an (nur lesbar) U3.30

2 Beispiel: Initialisierung eines Ports U3-12 I/O-Ports des AVR-mC Pin 3 von Port B (PB3) als Ausgang konfigurieren und auf V cc schalten: DDRB = 0x08; /* PB3 als Ausgang nutzen... */ PORTB = 0x08; /*...und auf 1 (=high) setzen */ Pin 0 von Port D (PD0) als Eingang nutzen, pull-up-widerstand aktivieren und prüfen ob ein low-pegel anliegt: DDRD &= ~0x01; /* PD0 als Eingang nutzen... */ PORTD = 0x01; /*...und den pull-up-widerstand aktivieren*/ if ( (PIND & 0x01) == 0) { /* den Zustand auslesen */ /* ein low Pegel liegt an, der Taster ist gedrückt */ } Die Initialisierung der Hardware wird in der Regel einmalig zum Programmstart durchgeführt U3.31 U3-13 Lebensdauer von Variablen U3-13 Lebensdauer von Variablen Die Lebensdauer einer Variablen bestimmt, wie lange der Speicherplatz für die Variable aufgehoben wird Zwei Arten statische (static) Variablen Speicherplatz bleibt für die gesamte Programmausführungszeit reserviert dynamische (automatic) Variablen Speicherplatz wird bei Betreten eines Blocks reserviert und danach wieder freigegeben U3.32

U3-13 Lebensdauer von Variablen (2) U3-13 Lebensdauer von Variablen auto-variablen Alle lokalen Variablen sind automatic-variablen der Speicher wird bei Betreten des Blocks / der Funktion reserviert und bei Verlassen wieder freigegeben der Wert einer lokalen Variablen ist beim nächsten Betreten des Blocks nicht mehr sicher verfügbar! Lokale auto-variablen können durch beliebige Ausdrücke initialisiert werden die Initialisierung wird bei jedem Eintritt in den Block wiederholt!!! wird eine auto-variable nicht initialisiert, ist ihr Wert vor der ersten Zuweisung undefiniert (= irgendwas) U3.33