Unterprogramme, Pointer und die Übergabe von Arrays



Ähnliche Dokumente
Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Einführung in die Java- Programmierung

Excel Funktionen durch eigene Funktionen erweitern.

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

Modellierung und Programmierung 1

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

2. Programmierung in C

Java Kurs für Anfänger Einheit 5 Methoden

Professionelle Seminare im Bereich MS-Office

Objektorientierte Programmierung. Kapitel 12: Interfaces

Einführung in die Java- Programmierung

Advoware mit VPN Zugriff lokaler Server / PC auf externe Datenbank

Felder, Rückblick Mehrdimensionale Felder. Programmieren in C

Objektorientierte Programmierung

icloud nicht neu, aber doch irgendwie anders

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Zur drittletzten Zeile scrollen

MdtTax Programm. Programm Dokumentation. Datenbank Schnittstelle. Das Hauptmenü. Die Bedienung des Programms geht über das Hauptmenü.

Second Steps in eport 2.0 So ordern Sie Credits und Berichte

Programmierkurs Java

Einrichtung eines Zugangs mit einer HBCI-Chipkarte bei der Commerzbank

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

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

SEMINAR Modifikation für die Nutzung des Community Builders

Datensicherung. Beschreibung der Datensicherung

Wir arbeiten mit Zufallszahlen

FORUM HANDREICHUNG (STAND: AUGUST 2013)

Fachbericht zum Thema: Anforderungen an ein Datenbanksystem

Zählen von Objekten einer bestimmten Klasse

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

Austausch- bzw. Übergangsprozesse und Gleichgewichtsverteilungen

VisualBasic - Variablen

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

1. Einschränkung für Mac-User ohne Office Dokumente hochladen, teilen und bearbeiten

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Zeichen bei Zahlen entschlüsseln

How to do? Projekte - Zeiterfassung

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Erklärung zum Internet-Bestellschein

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Grundlagen von Python

Arbeiten mit UMLed und Delphi

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Registrierung am Elterninformationssysytem: ClaXss Infoline

Der neue persönliche Bereich/die CommSy-Leiste

Programmieren Tutorium

Erwin Grüner

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können.

Artikel Schnittstelle über CSV

Durchführung der Datenübernahme nach Reisekosten 2011

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Internet online Update (Internet Explorer)

40-Tage-Wunder- Kurs. Umarme, was Du nicht ändern kannst.

Internet online Update (Mozilla Firefox)

Software Engineering Klassendiagramme Assoziationen

Um ein solches Dokument zu erzeugen, muss eine Serienbriefvorlage in Word erstellt werden, das auf die von BüroWARE erstellte Datei zugreift.

Theoretische Grundlagen der Informatik WS 09/10

FlowFact Alle Versionen

Vorkurs C++ Programmierung

LEITFADEN ZUR SCHÄTZUNG DER BEITRAGSNACHWEISE

AUTOMATISCHE -ARCHIVIERUNG. 10/07/28 BMD Systemhaus GmbH, Steyr Vervielfältigung bedarf der ausdrücklichen Genehmigung durch BMD!

Kurzeinführung LABTALK

Handbuch ECDL 2003 Modul 2: Computermanagement und Dateiverwaltung Dateien löschen und wiederherstellen

Informatik 2 Labor 2 Programmieren in MATLAB Georg Richter

Viele Bilder auf der FA-Homepage

Objektorientierte Programmierung für Anfänger am Beispiel PHP

DUALIS Web-Client Kurzanleitung für Studierende

1. EINLEITUNG 2. GLOBALE GRUPPEN Globale Gruppen anlegen

Vektoren mit GeoGebra

GEORG.NET Anbindung an Ihr ACTIVE-DIRECTORY

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = Euro ergeben.

HIER GEHT ES UM IHR GUTES GELD ZINSRECHNUNG IM UNTERNEHMEN

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

1 Vom Problem zum Programm

PowerPoint 2010 Mit Folienmastern arbeiten

Anbindung des eibport an das Internet

Persönliches Adressbuch

ARCO Software - Anleitung zur Umstellung der MWSt

Barcodedatei importieren

a n auf Konvergenz. Berechnen der ersten paar Folgenglieder liefert:

SJ OFFICE - Update 3.0

Adminer: Installationsanleitung

Zwischenablage (Bilder, Texte,...)

Um sich zu registrieren, öffnen Sie die Internetseite und wählen Sie dort rechts oben

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden.

IBIS Professional. z Dokumentation zur Dublettenprüfung

Updatehinweise für die Version forma 5.5.5

Installationsanleitung für CashPro im Mehrbenutzerzugriff/Netzwerkbetrieb

Erstellen der Barcode-Etiketten:

Handbuch ECDL 2003 Basic Modul 5: Datenbank Access starten und neue Datenbank anlegen

Lernwerkstatt 9 privat- Freischaltung

Weiterverarbeitung Leseranfragen

Einführung in die Programmierung

Outlook-Daten komplett sichern

Qt-Projekte mit Visual Studio 2005

Step by Step Webserver unter Windows Server von Christian Bartl

Lineare Gleichungssysteme

Aufklappelemente anlegen

Handbuch B4000+ Preset Manager

Tevalo Handbuch v 1.1 vom

Transkript:

Unterprogramme, Pointer und die Übergabe von Arrays Unterprogramme Wie schon im Abschnitt über Funktionen erwähnt, versteht man unter einem Unterprogramm im engeren Sinn eine Prozedur, welche die Werte der an sie übergebenen Variablen verändern darf. Im Gegensatz zu Funktionen, die nur einen einzigen Wert (eben den Funktionswert ) an das rufende Programm zurückliefern können (F kennt allerdings auch Array-wertige Funktionen), wird man also ein Unterprogramm dann verwenden, wenn das Ergebnis einer Berechnung aus mehreren Werten besteht. Es muß in der Parameterliste des Unterprogramms nur eine entsprechende Anzahl von Variablen zur Aufnahme dieser Werte vorgesehen werden. Zusätzlich kann ein Unterprogramm auch noch die Werte globaler Variablen verändern. Während C nicht zwischen Funktionen und Unterprogrammen unterscheidet (alle Prozeduren sind Funktionen), heißt in F ein Unterprogramm Subroutine und hat die folgende Gestalt subroutine subroutine name(argument list) type,intent(in)::arg sublist 1 type,intent(out)::arg sublist 2 type,intent(inout)::arg sublist 3 local declarations executable statements return end subroutine subroutine name Das Attribut intent bei der Deklaration der Argumente des Unterprogramms kennzeichnet, welche Parameter von der Prozedur nur gelesen (in), nur geschrieben (out) oder sowohl gelesen als auch geschrieben (inout) werden dürfen. Falls die Parameterliste argument list leer ist, kann mit dem rufenden Programm nur über globale Variablen kommuniziert werden. Für diese muß aber im Unterprogramm kein intent definiert werden. Unterprogramme müssen, ebenso wie Funktionen, in F in einen module-block eingeschlossen werden, und der Name des Unterprogramms muß global sichtbar gemacht werden: module module name private public::subroutine name contains subroutine subroutine name() end subroutine subroutine name 1

end module module name Der Aufruf eines Unterprogramms erfolgt mit dem Befehl call call subroutine name(argument list) Da in F Parameter per Adresse (call by name) übergeben werden, genügt es, in der Argumentliste einfach die Namen der zu übergebenden Variablen anzuführen. Das Unterprogramm greift direkt auf die Speicherplätze dieser Variablen zu, und alle an ihnen vorgenommenen Veränderungen sind im rufenden Programm unmittelbar sichtbar. Pointer In C sind alle Prozeduren Funktionen. Also muß man, um den Mechanismus von Unterprogrammen zu implementieren, Funktionen schreiben, die den Wert eines oder mehrerer Argumente verändern können. Da in C aber Argumente per Wert (call by value) übergeben werden, kann dies nur dadurch geschehen, daß man für jene Variablen, die vom Unterprogramm verändert werden sollen, nicht deren Wert, sondern ihre Adresse im Speicher übergibt. Dann kann, wie im Fall von F, das Unterprogramm direkt mit diesen Speicherinhalten rechnen, und alle Änderungen wirken sich automatisch im rufenden Programm aus. (Da solche Unterprogramme keinen Funktionswert im eigentlichen Sinn liefern, kann man ihnen den Typ void geben. Häufig definiert man sie auch als Typ int und gibt als Funktionswert einen ganzzahligen Code zurück, der anzeigt, ob im Unterprogramm Fehler aufgetreten sind oder nicht.) Die Adresse einer Variablen im Speicher liefert der Adreßoperator "&", der dem Namen der Variablen vorangestellt wird &x = Adresse der Variablen x Diese Konstruktion wird z.b. beim Aufruf der scanf- Funktion verwendet, wenn von der Tastatur die Werte von x und y eingelesen werden sollen scanf("%f,%f",&x,&y); Hier werden also die Adressen von x und y an das Unterprogramm übergeben, das damit unmittelbar auf die dort liegenden Speicherinhalte Zugriff hat und von sich aus mit den eingelesenen Werten überschreiben kann. Um im Unterprogramm mit diesen Adressen arbeiten zu können, braucht man Variablen zur Speicherung von Adressen. Solche Variablen nennt man Pointer, weil sie auf den Speicherplatz bzw. den dort gespeicherten Wert zeigen. (Pointer gibt es sowohl in F als auch in C, doch braucht man in F Pointer eher selten, und auch in C führt die sparsame Verwendung von Pointern zu lesbarerem und sichererem Code.) Obwohl Speicheradressen natürlich ganzzahlig sind, haben Pointer in C einen eigenen Typ, der sich nach dem Typ des Wertes richtet, auf den der Pointer zeigt, d.h. es gibt Pointer auf int, Pointer auf float usw. Pointer müssen deklariert werden wie andere Variablen auch 2

type *pointer 1,*pointer 2,; Dabei ist pointer 1, pointer 2,... der Name des Pointers und type der Typ des Wertes, auf den der Pointer zeigt. Den Wert an der Speicherstelle, auf die ein Pointer zeigt, erhält man mit dem Indirektionsoperator "*", der dem Namen des Pointers vorangestellt wird *p = an der Adresse p gespeicherter/zu speichernder Wert Mit den so angesprochenen Speicherinhalten kann man rechnen wie mit gewöhnlichen Variablen, d.h. sie können auf beiden Seiten von Zuweisungen vorkommen, z.b. float *xp,*yp,*zp; float u,v,w; xp=&u; yp=&v; zp=&w; u=*yp+w; *zp=*xp+v; Um also in C ein Unterprogramm zu schreiben, trennt man die Argumente in solche, die von der Prozedur nur gelesen [entsprechend intent(in) von F], und solche, die auch gesetzt werden [entsprechend intent(out) oder intent(inout)], und übergibt die ersteren per Wert, die letzteren aber per Adresse (Pointer), z.b. void sub(float rr1,float rr2,,float *ww1,float *ww2,) { *ww1=; *ww2=; int main() { float r1,r2,,w1,w2,; sub(r1,r2,,&w1,&w2,); 3

Übergabe von (mehrdimensionalen) Arrays in F Assumed-Shape Arrays Das allgemeine Problem bei der Übergabe von mehrdimensionalen Arrays an Unterprogramme besteht darin, daß alle (also auch mehrdimensionale) Arrays linear auf den Speicher abgebildet werden. So werden in F etwa die Elemente einer Matrix a(m,n) spaltenweise fortlaufend gespeichert a(1,1),, a(m,1), a(1,2),, a(m,2),,a(1,n),, a(m,n) d.h. das Element a(i,j) steht i+(j-1)*m-1 Positionen hinter der Startadresse (und wird auch mittels Startadresse plus Offset angesprochen). Um also auf die Elemente einer an das Unterprogramm übergebenen Matrix korrekt zugreifen zu können, muß demnach das Unterprogramm außer der Startadresse von a auch noch die Spaltenlänge m kennen. Die Übergabe von Arrays an Unterprogramme ist in F aber dennoch sehr einfach: Es muß nur die Startadresse (d.h. der Name) des Arrays explizit als Parameter übergeben werden, die Informationen über die Dimensionen des Arrays werden dann automatisch übertragen (aber nicht die Startwerte der Indizes, wenn diese nicht bei 1 beginnen). In den Deklarationen der Unterprogramm-Parameter kann man daher die Dimensionen solcher Arrays nach dem Muster dimension(:,:) unbestimmt lassen. Diesen Mechanismus nennt man Assumed-Shape Arrays. Die aktuelle Anzahl der Elemente in der Dimension dimension eines Arrays array kann man im Unterprogramm mit der size-funktion size(array,dimension) abfragen. Das folgende Beispiel zeigt die Übergabe einer Matrix und eines Vektors, dessen Startindex nicht 1, sondern imin ist subroutine sub1(a,v,imin) real,dimension(:,:),intent(in)::a real,dimension(imin:),intent(inout)::v integer::m,n m=size(a,1) n=size(a,2) end subroutine sub1 Automatic Arrays Häufig braucht man in Unterprogrammen temporäre Arrays, deren Größe von Aufruf zu Aufruf variieren kann. Solche Objekte muß man in F nicht explizit dynamisch erzeugen, sondern es genügt, sie als Automatic Arrays zu deklarieren. Das sind lokale Arrays, deren Dimensionen von den Parametern des Unterprogramms abhängig gemacht werden können. Im folgenden Beispiel sind b und c Automatic Arrays 4

subroutine sub2(a,m,) integer,intent(in)::m real,dimension(:,:),intent(inout)::a real,dimension(2*m)::b real,dimension(size(a,1))::c end subroutine sub2 Übergabe von (mehrdimensionalen) Arrays in C Bei der Verwendung von Arrays in C treten zwei Schwierigkeiten auf: Es besteht eine prinzipielle Inkonsistenz zwischen mehrdimensionalen Arrays fixer Größe und dynamisch erzeugten Arrays. Während die ersteren wie in F linear fortlaufend gespeichert sind (allerdings z.b. Matrizen zeilenweise) und über eine Startadresse plus Offset angesprochen werden, sind die letzteren stets Pointer auf einen Vektor von Pointern auf Objekte niedrigerer Dimensionalität (also im Fall einer Matrix ein Pointer auf einen Vektor von Pointern auf Zeilenvektoren) und daher i.a. nicht fortlaufend gespeichert. Ein Unterprogramm kann aber nicht unterscheiden, ob ein Array fix oder dynamisch erzeugt ist. Selbst wenn man sich auf Arrays von zur Compilationszeit bekannter (fixer) Größe beschränkt, fehlt ein Mechanismus, um im Unterprogramm z.b. die Zeilenlänge n einer als Parameter übergebenen Matrix zu vereinbaren, aus der der Compiler beim Auftreten von Matrixelementen der Form a[i][j] den Offset i*n+j für das Unterprogramm selbständig berechnen könnte. Es empfiehlt sich daher, in C alle Arrays dynamisch zu erzeugen und die syntaktische Verwandtschaft von Arrays und Pointern auszunützen. Diese besteht einerseits darin, daß man, wenn a ein Pointer ist, den Wert, der i Speicherstellen nach dem Wert steht, auf den der Pointer zeigt, sowohl in der Form *(a+i) als auch in der Form a[i] ansprechen kann. (Da aus dem Typ des Pointers hervorgeht, wieviel Platz zur Speicherung des Wertes notwendig ist, muß man den Pointer jeweils nur um 1 erhöhen, um auf den nächsten Wert im Speicher zu zeigen, unabhängig von der tatsächlichen Schrittweite in Bytes.) Andererseits ist diese Nomenklatur rekursiv, d.h. wenn a[i] kein Wert, sondern wiederum ein Pointer ist, dann kann man den Wert j Speicherstellen nach dem Wert, auf den der Pointer bei a[i] zeigt, mit a[i][j] ansprechen, usw. Um z.b. eine m*n Matrix a vom Typ float zu erzeugen, kann man folgendermaßen vorgehen: Es wird ein Pointer auf einen Vektor von Pointern vom Typ float definiert float **a; Der Speicherplatz für den Vektor von Pointern {a[0], a[1],..., a[m-1] muß mit malloc (oder calloc) angefordert werden a=(float**)malloc(m*sizeof(float*)); 5

(m ist die Anzahl der Zeilen der Matrix). Nun wird für jedes Element a[i] des Vektors von Pointern noch der Speicherplatz für die Zeile der Matrix reserviert, auf deren Beginn a[i] zeigen soll for(i=0;i<=m-1;i=i+1) { a[i]=(float*)malloc(n*sizeof(float)); (n ist die Anzahl der Spalten der Matrix). Die Matrixelemente können dann in der üblichen Form a[i][j] angesprochen werden. Das folgende Beispiel zeigt, wie man mit Hilfe dieses Mechanismus relativ einfach eine m*n Matrix a erzeugen und an ein Unterprogramm übergeben kann. Dabei müssen zwar die Dimensionen der Matrix explizit mitübergeben werden, damit man im Unterprogramm weiß, in welchen Bereichen sich (z.b. in Schleifen) die Indizes i und j bewegen dürfen; zur Berechnung der Adresse eines Elements a[i][j] braucht der Compiler aber nicht die Spaltenanzahl n, da die Adressen aller Zeilenanfänge in dem Pointer-Vektor a[i] stehen, auf den das Unterprogramm direkt zugreifen kann. void sub(float **a,int m,int n,) { int i,j,m,n; a[i][j]=; int main() { int i,m,n; float **a; a=(float**)malloc(m*sizeof(float*)); for(i=0;i<=m-1;i=i+1) { a[i]=(float*)malloc(n*sizeof(float)); sub(a,m,n,); 6