2. Programmierung in C

Ähnliche Dokumente
Programmierung mit C Zeiger

2. Programmierung in C

Zusammenfassung des Handzettels für Programmieren in C

Einführung in die Programmierung Arrays, Zeiger, Strings. Arvid Terzibaschian

Deklarationen in C. Prof. Dr. Margarita Esponda

Dr. Monika Meiler. Inhalt

Einheit Variablen in der Programmiersprache C Variablen-Modell, Variablen-Vereinbarungen

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Javaprogrammierung mit NetBeans. Variablen, Datentypen, Methoden

Programmieren in C++ Arrays, Strings und Zeigerarithmetik

Modul 122 VBA Scribt.docx

Programmiersprachen Einführung in C

Modellierung und Programmierung 1

Inhalt. 4.7 Funktionen

Einführung in die C++ Programmierung für Ingenieure

2. Programmierung in C

C allgemein. C wurde unter und für Unix entwickelt. Vorläufer sind BCPL und B.

9 Zeiger (Pointer). Dynamischer Speicher

Übung zur Vorlesung Programmieren in C

String s1, s2; Eine Zuweisung geschieht am einfachsten direkt durch Angabe des Strings eingeschlossen in doppelte Hochkommata:

C kompakt für Java-Programmierer

Ein erstes Java-Programm

Primitive Datentypen und Felder (Arrays)

Die Programmiersprache C99: Zusammenfassung

Zusammengesetzte Datentypen -- Arrays und Strukturen

Objektorientierte Programmierung OOP Programmieren mit Java

Unterprogramme, Pointer und die Übergabe von Arrays

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

C/C++ Programmierung

VisualBasic - Variablen

Einstieg in die Informatik mit Java

Modellierung und Programmierung

Grundlagen der Programmiersprache C++

Objektorientiertes Programmieren für Ingenieure

Übungen zur Vorlesung Computergrundlagen WS 2008/09 Fakultät Physik, Universität Stuttgart Jens Harting, Martin Hecht, Bibhu Biswal Blatt 14

Grundlagen der Informatik I (Studiengang Medieninformatik)

Die Programmiersprache C

Javakurs für Anfänger

Felder, Rückblick Mehrdimensionale Felder. Programmieren in C

Hello World. Javakurs 2014, 1. Vorlesung. Sebastian Schuck. basierend auf der Vorlage von Arne Kappen. wiki.freitagsrunde.org. 3.

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2

Einführung in die Programmiersprache C und in den C166-Compiler

Einführung in die Programmiersprache C

Gliederung. Tutorium zur Vorlesung. Gliederung. Gliederung. 1. Gliederung der Informatik. 1. Gliederung der Informatik. 1. Gliederung der Informatik

Datentypen. Agenda für heute, 4. März, Pascal ist eine streng typisierte Programmiersprache

Pass by Value Pass by Reference Defaults, Overloading, variable Parameteranzahl

Mikrocomputertechnik. Adressierungsarten

C-Propädeutikum Höhere Datentypen

Java Einführung Klassendefinitionen

Kurzeinführung in C++

Kurzeinführung in C. Johannes J. Schneider

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8

Inhaltsverzeichnis. Grundbegriffe der C-Programmierung Für den HI-TECH C-Compiler

Programmieren in C. C Syntax Datentypen, Operatoren und Kontrollstrukturen. Prof. Dr. Nikolaus Wulff

Objektorientierte Programmierung

Informationsverarbeitung im Bauwesen

2 Einfache Rechnungen

Einführung Datentypen Verzweigung Schleifen. Java Crashkurs. Kim-Manuel Klein May 4, 2015

Technische Infor matik 2 C/C++-Kurs. Pointer und Arrays AG Rechner netze 2.1

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 18

Prof. W. Henrich Seite 1

5.4 Klassen und Objekte

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl

Kapitel 7. Zusammengesetzte Datentypen, Vektoren, Zeichenketten

Java Kurs für Anfänger Einheit 2 Datentypen und Operationen

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

Tutorium Rechnerorganisation

Excel VBA Arrays, Enumeration und benutzerdefinierte Typen

3. Arrays und Pointer

1 Polymorphie (Vielgestaltigkeit)

2. Semester, 2. Prüfung, Lösung

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

Grundlagen der Programmierung Prof. H. Mössenböck. 6. Methoden

Fakultät Angewandte Informatik Lehrprofessur für Informatik

Programmiersprachen Einführung in C. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm

5. Unterprogrammtechnik/Module

Einführung in die Java- Programmierung

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala

Die Programmiersprache C Eine Einführung

Kurze Einführung in die Programmiersprache C++ und in Root

Computeranwendung und Programmierung (CuP)

Informatik. Studiengang Chemische Technologie. Michael Roth WS 2012/2013. Hochschule Darmstadt -Fachbereich Informatik-

Einführung in die Informatik für Hörer aller Fakultäten II. Andreas Podelski Stephan Diehl Uwe Waldmann

Moderne C-Programmierung

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Zugriff auf die Modul-EEPROMs

Datentypen: Enum, Array, Struct, Union

IT-Basics 2. DI Gerhard Fließ

L6. Operatoren und Ausdrücke

Primitive Datentypen

magnum C++ WALTER SAUMWEBER kompakt komplett kompetent

Objective-C CheatSheet

2. Programmierung in C

Objektorientierte Programmierung

Algorithmische Kernsprache. Zuweisung, einfache und bedingte Anweisung, Blöcke, Schleifen, return, debugging.

Proseminar C-Programmierung. Strukturen. Von Marcel Lebek

Transkript:

2. Programmierung in C Inhalt: Überblick über Programmiersprachen, Allgemeines zur Sprache C C: Basisdatentypen, Variablen, Konstanten, Operatoren und Ausdrücke Anweisungen und Kontrollstrukturen (Steuerfluss) Funktionen Felder (Arrays) Zeiger, Zeigerarithmetik, Zeiger-Dereferenzierung Zeichenketten (Strings) Benutzerdefinierte Datentypen Speicherverwaltung und Datenstrukturen Dateiarbeit Bitlevel-Verarbeitung

Zeiger (engl. Pointer) Zeiger Ein Zeiger (engl. Pointer) speichert eine Adresse. Eine Variable im Gegensatz speichert einen Wert. Der Name eines Zeigers ist mit einer Adresse verbunden, ein Variablenname dagegen mit einem bestimmten Wert. Zeiger werden z.b. für folgende Zwecke benutzt: Dynamische Speicherverwaltung Parameterübergabe in Funktionen Zeichenkettenverarbeitung

Definition von Zeigervariablen Bei der Definition eines Zeigers wird ein Stern ("*") vor den Bezeichner geschrieben. Werden die Bezeichner mit Kommas getrennt in einer Definitionsliste angegeben, so muss der Stern vor jeden einzelnen Bezeichner geschrieben werden, der als Zeiger definiert werden soll. long *LZ, LZ2; // LZ ist ein Zeiger, LZ2 eine Variable float summe, * psumme; // summe ist eine Variable, // psumme ein Zeiger Für eine gute Übersichtlichkeit, besser Variablen und Zeiger in jeweils einer eigenen Zeile definieren! float summe; float* psumme;

Veranschaulichung einer Zeigervariablen Der Speicher eines Rechners wird über Adressen verwaltet, die die Speicherstellen (Bytes) linear durchnummerieren. Die Nummer des angesprochenen Bytes ist die Adresse. Hier ein Beispiel (stark vereinfacht) : float summe; float* psumme = &summe; // Zeiger mit Adresse von summe 4 Inhalt 0 1 4 summe 12 psumme Adresse Zugriff auf summe wird durch Compiler mit Zugriff auf Adresse 4 ersetzt

Der &-Operator Zeiger - Adressoperator Um die Adresse einer Variablen zu erhalten, muss ein spezieller Operator verwendet werden. Dieser Operator wird als Adressoperator bezeichnet. Er wird mit dem Zeichen "&" (Ampersand) symbolisiert. Zum Beispiel: int Io = 1024; int* IZ = &Io; // IZ erhält die Adresse von Io // und nicht den Wert 1024

Zeiger Ein Zeiger kann auch mit einem anderen Zeiger desselben Typs initialisiert werden. // jetzt enthält auch IZ2 die Adresse von Io int* IZ2 = IZ; int ** IZ4 = &IZ; // Zeiger auf Zeiger

Beispiele zur Benutzung von Zeigern void swap(float* x1, float* x2) { // zwei Werte vertauschen float temp = *x1; *x1 = *x2; *x2 = temp; } void swap2(float** x1, float** x2) { // zwei Zeiger vertauschen float* temp = *x1; *x1 = *x2; *x2 = temp; } int main(void) { float a, b, *pa, *pb; a = 1.0, b = 2.0, pa = &a, pb = &b; swap(&a, &b); /* Tauscht die Werte a und b wirklich* / swap2(&pa, &pb); /* tauscht nur die Pointer */ }

Der * - Operator * ist der Inhaltsoperator. Damit kann ein Zeiger dereferenziert werden, d.h. auf den Wert der Variable (auf die gezeigt wird) zugegriffen werden. Die Vereinbarung int* pi; oder auch int *pi; kann gelesen werden als der Inhalt von pi ist vom Typ int, also ist pi vom Typ Zeiger auf int : int i = 1234; int* pi; // pi ist also vom Typ Zeiger auf int pi = &i; // pi zeigt jetzt auf i *pi = 5678; // i hat jetzt den Wert 5678, // der Zugriff auf i erfolgt hier durch Dereferenzieren // des Zeigers pi. Dereferenzierung: Typ* ptr; // hier wird eine Zeigervariable definiert *ptr =...;... = *ptr; // hier wird ptr dereferenziert // und damit auf den Inhalt zugegriffen

Zeiger und Typen Jeder Zeiger ist mit einer Variablen eines bestimmten Typs verbunden Der Datentyp gibt den Typ des Datenobjekts an, das mit Hilfe dieses Zeigers adressiert wird. Ein Zeiger des Typs int zeigt zum Beispiel auf ein Objekt des Typs int. int intvar; int* intzeiger = &intvar; Um auf ein Objekt des Typs double zu zeigen, muss der Zeiger mit dem Datentyp double definiert werden. double dvar; double* dzeiger = &dvar;

Zeiger - Speicherbedarf von Zeigern Der Speicherplatz, der für einen Zeiger reserviert wird, muss eine Speicheradresse aufnehmen können. Das bedeutet, dass ein Zeiger des Typs int und ein Zeiger auf einen Datentyp double normalerweise gleich groß sind. Der Typ, der einem Zeiger zugeordnet ist, gibt den Inhalt und damit auch die Größe des adressierten Speicherbereichs an. int* pint ; // pint belegt 4 Byte double* pdouble; // pdouble belegt auch 4 Byte Der Speicherplatz der für Zeiger verwendte wird ist implementierungsabhängig und typischerweise 32 oder 64 Bit (d.h. 4 oder 8 Byte lang).

Zugriff auf Felder durch Zeiger (1) In C sind Variablen für Felder und Zeiger zuweisungskompatibel. Beispiel: int zahlenfeld[20]; int einzelzahl; int *iptr; iptr = zahlenfeld; // dem Zeiger kann der Name eines Feldes // zugewiesen werden einzelzahl = iptr[5]; // Ein Zeiger kann wie ein Feld benutzt werden Ein Feld mit Elementen eines bestimmten Typs wird als Variable wie ein Zeiger auf ein Element des Typs behandelt. Gleichzeitig kann ein Zeiger auch wie ein Feldbezeichner mit Indexklammern versehen werden.

Zugriff auf Felder durch Zeiger (2) Hintergrund: int feld[10]; int* ptr = feld; // entspricht: int* ptr = &feld[0] Der Feldname entspricht damit der Adresse des ersten Feldelementes, d.h. dem mit dem Index 0. Der Zusammenhang zwischen Feldern und Zeigern wird oft bei der Übergabe von Feldern in Funktionsparametern ausgenutzt: void auswahlfunktion( int *feld, int index, int *wert ) { *wert = feld [index]; }

Addition und Subtraktion bei Zeigern Bei der Addition (oder Subtraktion) eines ganzzahligen Wertes (z.b. 2), wird der Wert der entsprechenden Adresse um die Größe von z.b. zwei Objekten dieses Datentyps (hier int) erhöht (oder erniedrigt). Wenn z.b. ein char 1 Byte, ein int 4 Byte und ein double 8 Byte belegt, dann erhöht sich bei einer Addition um 2 zu einem Zeiger, der Wert der im Zeiger gespeicherten Adresse um 2, 8 bzw. 16 Byte. Beispiele: int i; // z.b. Adresse 0x0100 int j; // z.b. Adresse 0x0104 int k; // z.b. Adresse 0x0108 int feld[10]; // z.b. Adresse 0x010C, 0x0110, 0x0114... int* ptr = & i; // ptr enthält Adresse von i, d.h 0x0100 ptr = ptr + 2; // ptr enthält nun 0x0108, d.h. Adresse von k ptr++; // ptr enthält nun 0x010C, d.h. Adresse feld[0]

Operationen mit Zeigern (1) Einem Zeiger kann man einen Zeiger des gleichen Typs zuweisen. int* ptr1 = &i; int* ptr2 = ptr1; Ein Zeiger kann auch inkrementiert oder dekrementiert werden. So bedeutet z.b. +5 hier eine Inkrementierung um 5 Schritte mit der Schrittweite sizeof(int) : int* ptr3 = ptr2 + 5; Eine Zuweisung eines anderen Typs ist nur über Typecast möglich: char* pchar = (char*) ptr2; // typecast

Operationen mit Zeigern (2) Es kann die Differenz zweier Zeiger gebildet werden: int feld[10]; int* ptr1 = &feld[1]; int* ptr8 = &feld[8]; int anzahl = ptr8 ptr1; // ergibt den Wert 7 // Besser: ptrdiff_t anzahl = ptr8 ptr1; ( ptrdiff_t ist in cstddef bzw. stddef.h vereinbart ) Einem Zeiger darf der Wert 0 (NULL) zugewiesen werden. Dadurch wird der Zeiger als nicht initialisierter Zeiger gekennzeichnet: int* ptr = 0; // oder: int* ptr = NULL; Die Vergleichsoperationen == und!= sind zulässig, um zwei Zeiger auf Gleichheit zu testen, d.h. ob sie auf die gleiche Adresse verweisen. Dieses hat nichts mit den Werten zu tun, die die Adressen enthalten.

Es gibt einen besonderen Zeigerwert, der als Konstante NULL definiert ist. Die interne Darstellung der NULL ist implementierungsabhängig, aber kompatibel zur ganzzahligen Null (0). NULL kann jeder Zeigervariablen zugewiesen werden, und jede Zeigervariable kann auf NULL getestet werden; p = NULL; /* Beide Anweisungen sind */ p = 0; /* korrekt und bedeutungsgleich! */... if (p==null)... /* Alle drei */ if (!p)... /* Abfragen sind korrekt */ if (p==0)... /* und bedeutungsgleich! */ Diese Operationen können auch dazu verwendet werden, um zu ermitteln, ob ein Zeiger bereits initialisiert wurde: int *ptr = 0, *ptr2;... if (ptr == 0) { // initialisiere jetzt ptr } NULL - Zeiger

Weitere Bedeutung von Zeigern Zeiger zur Übergabe von Parametern an Funktionen Call by Reference Parameter sind Zeiger void function(int x, int *y) { *y = 2*x*x 3*x +5; // der Wert auf den y zeigt wird verändert } Zeiger für dynamische Speicherstrukturen int *p; int anzahl_werte; // konkreter Wert ergibt sich zur Laufzeit p = malloc(anzahl_werte*sizeof(int));