documentc

79
TUHH Rechenzentrum Die Programmiersprache C 1 Einleitung 1.1 Übersicht Einleitung Übersicht Einige grundlegende Begriffe Geschichtliche Entwicklung, Einordnung Ein erstes Programm Grundelemente der Sprache C Grundlegende Datentypen Arithmetische Datentypen, Konstanten, Variablen, Zeiger, Felder, Speicherklassen, Typattribute, Operatoren, Typumwandlung Kontrollstrukturen Blockanweisung, Verzweigungs-Anweisungen, Wiederholungs-Anweisungen, spezielle Anweisungen Höhere Datentypen Benutzerdefinierte Datentypen, Mehrdimensionale Felder, Strukturen und Varianten Ergänzung: Aufzählungstyp, Bitfelder Funktionen Argumente der main-Funktion, variable Parameteranzahl, Unterschiede: ANSI-C — K&R-C Standardbibliotheken Beispiele Einführung in C Dirk Husung Übersicht (1)

Upload: sattar-al-jabair

Post on 27-Dec-2015

11 views

Category:

Documents


2 download

DESCRIPTION

c

TRANSCRIPT

Page 1: Documentc

TUHHRechenzentrum

Die Programmiersprache C

1 Einleitung1.1 Übersicht

◦ EinleitungÜbersichtEinige grundlegende BegriffeGeschichtliche Entwicklung, EinordnungEin erstes ProgrammGrundelemente der Sprache C

◦ Grundlegende DatentypenArithmetische Datentypen, Konstanten, Variablen, Zeiger, Felder,Speicherklassen, Typattribute, Operatoren, Typumwandlung

◦ KontrollstrukturenBlockanweisung, Verzweigungs-Anweisungen,Wiederholungs-Anweisungen, spezielle Anweisungen

◦ Höhere DatentypenBenutzerdefinierte Datentypen,Mehrdimensionale Felder, Strukturen und VariantenErgänzung: Aufzählungstyp, Bitfelder

◦ FunktionenArgumente der main -Funktion, variable Parameteranzahl,Unterschiede: ANSI-C — K&R-C

◦ Standardbibliotheken

◦ Beispiele

Einführung in CDirk Husung

Übersicht (1)

Page 2: Documentc

TUHHRechenzentrum

1.2 Einige grundlegende Begriffe

Algorithmus:

Eine endliche, eindeutige Schrittfolge von Ope-rationen, die als allgemeines Verfahren die Lö-sung einer Klasse von Problemen zum Ziel hat.

Programm:

Die Formulierung eines Algorithmus’ und der zu-gehörigen Datendarstellung in einer Program-miersprache.

Machinensprache — Assembler —Hochsprache

Interpreter — Compiler

Einführung in CDirk Husung

Einige grundlegende Begriffe (1)

Page 3: Documentc

TUHHRechenzentrum

(primitiver) Datentyp:

(Wertemenge, Operationenmenge)

Datenobjekt :

kann Wert aufnehmen

Systemzustand:

bestimmt durch aktuelle Werte aller Datenobjek-te

Operation:

Aktion, abhängig von Argumenten und System-zustand

Abstrakter Datentyp (ADT):

(Wertemenge(n), Operationenmenge)

nach außen wie primitiver Datentyp. Beispiel: Intervalle.

Abstraktes Datenobjekt:

(Abstrakter Datentyp, Objekt)

ADT, dessen Operationen abhängen von Argumenten,

Systemzustand und „Gedächtnis“ des ADTs; beeinflußt

das „Gedächtnis“ die Operationen nicht, liegt ein Abstrak-

ter Datentyp vor. Beispiel: Warteschlange.

Einführung in CDirk Husung

Einige grundlegende Begriffe (2)

Page 4: Documentc

TUHHRechenzentrum

1.3 Geschichtliche Entwicklung,

Einordnung

Anfang der 70er Jahre wurde C von Dennis M.Ritchie an den Bell Laboratories entworfen zumSchreiben von Systemprogrammen für eine DECPDP-11.

C ist Nachfolger von BCPL bzw. B, bei denen essich jedoch im Gegensatz zu C um typenlose Spra-chen handelt. C wurde verallgemeinert und auf ei-ne Vielzahl von Rechnern portiert. Es wird durcheine umfassende Menge von Werkzeugen im Be-triebssystem UNIX unterstützt. UNIX selbst ist zuüber 90% in C implementiert.

Ende 1989 erfolgte die Standardisierung von Cdurch das ANSI X3J11 Komitee.

Seitdem entwickelte sich C zu der am häufigstenverwendeten Sprache in der professionellen Soft-wareentwicklung.

Einführung in CDirk Husung

Geschichtliche Entwicklung, Einordnung (1)

Page 5: Documentc

TUH

HRe

che

nzentrum

Einordnung von Programmiersprachen

FORTRAN ’57 LISP ’59

BASIC ’78 ALGOL 60 ’60 COBOL ’68

APL ’68 ALGOL 68 ’77 PL/1 ’66 LOGO ’68

PASCAL ’70 BCPL ’67 SIMULA 67 ’69 PROLOG ’81

MODULA-2 ’80 ADA ’83 PEARL ’77 C ’72 SMALLTALK ’80

OBERON ’88 C++ ’84

Einführung

inC

Dirk

Husung

Geschichtliche

Entw

icklung,Einordnung

(2)

Page 6: Documentc

TUHHRechenzentrum

1.4 Ein erstes Programm

/***************************************** Ein erstes Programm: Hello, World!*****************************************/

#include <stdio.h>

int main (void){

printf ("Hello, World!\n");return (0);

} /* main */

Einführung in CDirk Husung

Ein erstes Programm (1)

Page 7: Documentc

TUHHRechenzentrum

1.5 Grundelemente der Sprache C

Folgende Zeichen sind in C-Programmen zulässig:

• die alphanumerischen Zeichen:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Za b c d e f g h i j k l m n o p q r s t u v w x y z0 1 2 3 4 5 6 7 8 9

• die folgenden Sonderzeichen:( ) [ ] { } < > + - * / % ^ ~& | _ = ! ? # \ , . ; : ’ "

• Leerzeichen, (horizontaler) Tabulator, Zeilen-endezeichen, vertikaler Tabulator und Zeilenvor-schub.

Die nachfolgenden Schlüsselwörter sind in C reser-viert. Sie können nur in ihrer vordefinierten Bedeu-tung verwendet werden:

auto double int struct

break else long switch

case enum register typedef

char extern return union

const float short unsigned

continue for signed void

default goto sizeof volatile

do if static while

Einführung in CDirk Husung

Grundelemente der Sprache C (1)

Page 8: Documentc

TUHHRechenzentrum

2 Grundlegende Datentypen

2.1 Arithmetische Datentypen

Typ Speicherplatzbedarf

char 1 Bytesigned char 1 Byteunsigned char 1 Byte

short [int ] 2 Bytessigned short [int ] 2 Bytesunsigned short [int ] 2 Bytes

int maschinenabhängig 2 oder 4 Bytessigned int maschinenabhängig 2 oder 4 Bytesunsigned int maschinenabhängig 2 oder 4 Bytes

long [int ] 4 Bytessigned long [int ] 4 Bytesunsigned long [int ] 4 Bytes

float 4 Bytesdouble 8 Bytes

long double maschinenabhängig 8, 10 oder16 Bytes

Einführung in CDirk Husung

Arithmetische Datentypen (1)

Page 9: Documentc

TUHHRechenzentrum

Bemerkungen:

• Der char -Typ kann compilerabhängig vorzei-chenbehaftet oder vorzeichenlos sein.

• Der jeweilige Speicherplatzbedarf kann mit demsizeof -Operator bestimmt werden (durch denPräprozessor!). Es gilt:sizeof (short) ≤ sizeof (int) ≤ sizeof (long) .

• Die Wertebereiche der Datentypen sind durchKonstanten in den Header-Dateien limits.hfür ganzzahlige Typen und float.h für Gleit-punkttypen beschrieben; z.B.:#define SHRT_MIN (-32768)#define SHRT_MAX 32767#define LONG_MIN ((long)0x80000000)#define LONG_MAX 0x7fffffff

#define DBL_MIN 2.2250738585072014e-308

#define DBL_MAX 1.7976931348623151e+308

• C besitzt keinen gesonderten booleschen Typ.Es gilt:ganzzahliger Wert == 0⇔ FALSEganzzahliger Wert != 0⇔ TRUE

• C besitzt keinen Mengentyp, jedoch weitreichen-de Möglichkeiten der Bitmanipulation (s.u.).

Einführung in CDirk Husung

Arithmetische Datentypen (2)

Page 10: Documentc

TUHHRechenzentrum

IEEE-double -Format:

sign biased exponent significant1 bit 11 bits 52 bitsmsb lsb

normal 0/1 11 . . . 10 [1.]11 . . . 11 ∗ 2exponent−1023

... ...00 . . . 01 [1.]00 . . . 00

denormal 0/1 00 . . . 00 [0.]11 . . . 11 ∗ 2−1022

... ...00 . . . 00 [0.]00 . . . 01

0 0/1 00 . . . 00 00 . . . 00

+∞ 0 11 . . . 11 00 . . . 00

−∞ 1 11 . . . 11 00 . . . 00

nan 0/1 11 . . . 11 11 . . . 11... ...

11 . . . 11 00 . . . 01

Einführung in CDirk Husung

Arithmetische Datentypen (3)

Page 11: Documentc

TUHHRechenzentrum

2.2 Konstanten

Ganzzahlige Konstanten

Konstante Typ

1234 int

1234U unsigend int

12345678L long

134217728UL unsigend long

0x8000000UL unsigned long , hexadezimalHexziffern: 0–9, A–F, a–f .

007 char , oktal

Gleitkommakonstanten

Konstante Typ

12.7 double

1e5 double

2.0E-3 double

12.7f float

1e5f float

2.0E-3l long double

Einführung in CDirk Husung

Konstanten (1)

Page 12: Documentc

TUHHRechenzentrum

Zeichen

Konstante Typ

’a’ char

’\007’ char , oktale Notation (hier: ’\a’ )’\x0A’ char , hexadezimale Notation (hier: ’\n’ )’\n’ char , Escape-Sequenz’\’’ char , Escape-Sequenz

Zeichenketten

Zeichenketten sind Felder von Zeichen mit einemzusätzlichen abschließenden 0-Zeichen.

Konstante Typ

"string" char *

"\"string\"" char * , Escape-Sequenz

Wichtig:

’x’ belegt 1 Byte"x" belegt 2 Bytes (0-terminierte Zeichenkette)

Einführung in CDirk Husung

Konstanten (2)

Page 13: Documentc

TUHHRechenzentrum

2.3 Variablen

• Variablen sind benannte Datenobjekte, die einenWert aufnehmen können.

• Variablennamen bestehen aus einer Folge vonBuchstaben und Ziffern, beginnend mit einemBuchstaben. Der Unterstrich „_“ zählt dabei zuden Buchstaben.

• Zwischen Groß- und Kleinbuchstaben wird un-terschieden.

• Variablen sind vor Benutzung zu deklarieren;z.B.:extern unsigned int uMemoryUsed;

• Sie sind an genau einer Stelle im Programm zudefinieren. Erst mit der Variablendefinition wirdSpeicherplatz belegt; z.B.:unsigned int uMemoryUsed;

• Variablen können bei ihrer Definition initialisiertwerden; z.B.:unsigned int uMemoryUsed = 0;

Einführung in CDirk Husung

Variablen (1)

Page 14: Documentc

TUHHRechenzentrum

2.4 Zeiger, Felder, Adreßarithmetik

Beispiel:

int i = 1;int * pi = & i;int aiVector [4] = {

1, 2, 3, 4};int * piVector = aiVector;

piVector++;i = piVector - aiVector;

0x10000:0x10004:0x10008: 1 i

0x1000C: 0x10008 pi

0x10010: 1 aiVector[0] ← aiVector

0x10014: 2 aiVector[1]

0x10018: 3 aiVector[2]

0x1001C: 4 aiVector[3]

0x10020: 0x10010 piVector

0x10024:0x10028:

Einführung in CDirk Husung

Zeiger, Felder, Adreßarithmetik (1)

Page 15: Documentc

TUHHRechenzentrum

Das Wichtigste in Stichpunkten:

• Zeiger-Variablen dürfen anderen Zeiger-Varia-blen gleichen Typs zugewiesen werden.

• Der Wert NULL kann jedem Zeiger zugewiesenwerden. NULL verweist auf kein existierendesObjekt.

• Zeiger-Variablen dürfen verglichen werden (==,!= , <, <=, >, >=).

• Zeiger-Variablen können inkrementiert und de-krementiert werden (skalierte Zeigerarithmetik).

• Der Abstand zwischen Zeigern kann ermitteltwerden, sofern die Zeiger auf einen zusammen-hängenden Speicherbereich verweisen.

Felder werden repräsentiert durch einen Zeiger aufdas erste Feldelement.

Die Feldelemente tragen die Indizes 0,1,. . .

Einführung in CDirk Husung

Zeiger, Felder, Adreßarithmetik (2)

Page 16: Documentc

TUHHRechenzentrum

2.5 Speicherklassen

Speicherklasse Beschreibung

auto Standard, optional.Sichtbarkeit: außerhalb aller Funktionen pro-grammweit, innerhalb einer Funktion be-schränkt auf den aktuellen Block.Lebensdauer: außerhalb aller Funktionenüber die gesamte Programmlaufzeit, inner-halb einer Funktion für die Ausführung desbetreffenden Blocks.Initialisierung: außerhalb aller Funktionenmit 0, sonst undefiniert, wenn nicht explizitangegeben.

static Sichtbarkeit: außerhalb aller Funktionen mo-dulweit, innerhalb einer Funktion beschränktauf den betreffenden Block.Lebensdauer: über die gesamte Programm-laufzeit.Initialisierung: mit 0, wenn nicht explizit an-gegeben.

extern Deklaration, Definition i.a. in einem anderenModul außerhalb aller Funktionen als auto .

register wie auto , jedoch Empfehlung an den Com-piler, die betreffende Variable in einem Pro-zessorregister zu halten.

Einführung in CDirk Husung

Speicherklassen (1)

Page 17: Documentc

TUHHRechenzentrum

Beispiel:

#include <stdio.h>

int main (void){

int i;

for (i = 0; i < 3; i++) {int k = 0; /* beliebiger Ausdruck */printf ("%4d", k++);

}

for (i = 0; i < 3; i++) {static in t k = 0; /* konstanter Ausdruck */printf ("%4d", k++);

}

return (0);} /* main */

Ausgabe:

0 0 0 0 1 2

Einführung in CDirk Husung

Speicherklassen (2)

Page 18: Documentc

TUHHRechenzentrum

2.6 Typattribute

Attribut Beschreibung

const legt fest, daß eine Variable nicht geän-dert werden darf, auch nicht komponen-tenweise (Felder, Strukturen); z.B.:const double e = 2.7183;

volatile zeigt an, daß eine Variable jederzeit ge-ändert werden kann, auch in nicht offen-sichtlicher Weise etwa im Verlauf einerInterrupt-Behandlung (⇒ Einschränkungfür Compileroptimierungen).

Beispiel:

int * pi; Zeiger auf ein Objekt vom Typint

int * const pi; konstanter Zeiger auf ein Ob-jekt vom Typ int

const int * pi; Zeiger auf ein konstantes Ob-jekt vom Typ int

const int * const pi; konstanter Zeiger auf ein kon-stantes Objekt vom Typ int

Einführung in CDirk Husung

Typattribute (1)

Page 19: Documentc

TUHHRechenzentrum

2.7 Operatoren

• Arithmetische Operatoren

• Inkrement-, Dekrementoperator

• Vergleichsoperatoren

• Operatoren zur Bitmanipulation

• Logische Operatoren

• sizeof-Operator

• Bedingter-Ausdruck-Operator

• Zuweisungsoperatoren

• Sonstige Operatoren

Anmerkung:

Die Zuweisung zählt in C zu den Operatoren.Es gibt in C keine benutzerdefinierten Operatoren.

Einführung in CDirk Husung

Operatoren (1)

Page 20: Documentc

TUHHRechenzentrum

Reihenfolge der Ausdrucksauswertung:

1. entsprechend der Klammerung

2. entsprechend der Priorität der Operatoren

3. entsprechend der Assoziativität der Operatorenvon rechts nach links bei

• monadischen Operatoren

• bedingten Ausdrücken

• Zuweisungen

4. entsprechend der Assoziativität der Operatorenvon links nach rechts bei

• arithmetischen Operatoren

• Vergleichsoperatoren

• Operatoren zur Bitmanipulation

Wichtig:

In C ist i.a. nicht festgelegt, in welcher Reihenfol-ge die Operanden eines Operators (oder auch dieArgumente einer Funktion) ausgewertet werden.

Ausnahmen: &&, || , ?:Hier erfolgt die Auswertung der Operanden garan-tiert von links nach rechts.

Einführung in CDirk Husung

Operatoren (2)

Page 21: Documentc

TUHHRechenzentrum

bitweiser Operator &:

char a = 0xE4; /* 1110 0100 */char b = 0xCC; /* 1010 1010 */char r = a & b; /* 1010 0000 */

bitweiser Operator | :

char a = 0xE4; /* 1110 0100 */char b = 0xCC; /* 1010 1010 */char r = a | b; /* 1110 1110 */

bitweiser Operator ^ :

char a = 0xE4; /* 1110 0100 */char b = 0xCC; /* 1010 1010 */char r = a ^ b; /* 0100 1110 */

bitweiser Operator ~:

char a = 0xE4; /* 1110 0100 */char r = ~a; /* 0001 1011 */

Einführung in CDirk Husung

Operatoren (3)

Page 22: Documentc

TUHHRechenzentrum

bitweiser Operator >>:

signed char a = 0xE4; /* 1110 0100 */signed char r = a >> 1; /* ?111 0010 */unsigned char ua = 0xE4; /* 1110 0100 */unsigned char ur = ua >> 1; /* 0111 0010 */

bitweiser Operator <<:

char a = 0xE4; /* 1110 0100 */char r = a << 1; /* 1100 1000 */

logischer Operator &&:

char a = 0xE4; /* 1110 0100 */char b = 0xCC; /* 1010 1010 */char r = a && b; /* 0000 0001 */

logischer Operator || :

char a = 0xE4; /* 1110 0100 */char b = 0xCC; /* 1010 1010 */char r = a || b; /* 0000 0001 */

logischer Operator ! :

char a = 0xE4; /* 1110 0100 */char r = !a; /* 0000 0000 */

Einführung in CDirk Husung

Operatoren (4)

Page 23: Documentc

TUHHRechenzentrum

2.8 Typumwandlung

Implizite Typumwandlung

Werden Operanden unterschiedlichen arithmeti-schen Typs miteinander verknüpft, erfolgt eine Typ-anhebung:

x * ld → (long double) x * ld , sonstx * d → (double) x * d , sonstx * f → (float) x * f , sonst

nach Erweiterung auf int , wenn möglich, sonstnach Erweiterung auf unsigend int :

x * ul → (unsigned long ) x * ul , sonstu * l → (long) u * l , sonstu * l → (unsigned long) u *

(unsigned long) l , sonstx * l → (long) x * l , sonstx * u → (unsigned int) x * u

darin bezeichnen:

ld einen long double Operandend einen double Operandenf einen float Operandenul einen unsigend long Operandenl einen long Operandenu einen unsigned int Operandenx einen Operanden sonstigen Typs

Einführung in CDirk Husung

Typumwandlung (1)

Page 24: Documentc

TUHHRechenzentrum

Explizite Typumwandlung

Der expliziten Typumwandlung dient der cast-Ope-rator.

Beispiel: Zugriff auf die einzelnen Bytes einer int -Variablen i :

((unsigned char *) & i)[0];:

((unsigned char *) & i)[sizeof(i)-1];

Einführung in CDirk Husung

Typumwandlung (2)

Page 25: Documentc

TUHHRechenzentrum

3 Kontrollstrukturen

3.1 Block-Anweisung

Jede Anweisung kann eine Block-Anweisung sein.Innerhalb jedes Anweisungsblocks ist die Definitionlokaler Variablen möglich.

{definitionsstatements

}

{int t = a;a = b; b = t;

}

Einführung in CDirk Husung

Block-Anweisung (1)

Page 26: Documentc

TUHHRechenzentrum

3.2 Verzweigungs-Anweisungen

if -, if -else -Anweisung

if ( int_expr)statement

if (i < 10) {element[0][i] = i;element[1][i] = i*i;

}

1

statement

3

ja

int_expr != 0

2

4

if ( int_expr)statement1

elsestatement2

if (i < 2)element[i] = i;

elseelement[i] = element[i-2]

+ element[i-1];

1

statement2

4

statement1

3

ja nein

int_expr != 0

2

5

Einführung in CDirk Husung

Verzweigungs-Anweisungen (1)

Page 27: Documentc

TUHHRechenzentrum

switch -Anweisung

switch ( int_expr) {case int_const:

statements[break; ]

default:statements

}

switch (c) {case ’\n’: /* Zeilenende */

number_of_lines++;

case ’\t’: /* Tabulator oder */case ’ ’ : /* Leerzeichen */

number_of_words++;break;

default: /* bel. sonstiges Zeichen */number_of_characters++;break;

}

Einführung in CDirk Husung

Verzweigungs-Anweisungen (2)

Page 28: Documentc

TUHHRechenzentrum

3.3 Wiederholungs-Anweisungen

while -Anweisung

while ( int_expr)statement

i = 0;while (i < DIM) {

element[0][i] = i;element[1][i] = i*i;i++;

}

for -Anweisung

for ( init_expr; int_expr; reinit_expr)statement

„äquivalent“ zu:

init_expr;while ( int_expr) {

statementreinit_expr;

}

for (i = 0; i < DIM; i++) {element[0][i] = i;element[1][i] = i*i;

}

do-while -Anweisung

do {statements

} while ( int_expr);

do {element[0][i] = i;element[1][i] = i*i;

} while (++i < DIM);

Einführung in CDirk Husung

Wiederholungs-Anweisungen (1)

Page 29: Documentc

TUHHRechenzentrum

while ( int_expr )statement

for ( init_expr ;int_expr ; reinit_expr )

statement

do {statement

} while ( int_expr );

int_expr != 0

2

1

statement

3

4

nein

int_expr != 0

4

statement

5

1

init_expr

2

reinit_expr

6

nein

7

3

statement

2

int_expr != 0

3

1

4

ja

Einführung in CDirk Husung

Wiederholungs-Anweisungen (2)

Page 30: Documentc

TUHHRechenzentrum

3.4 Spezielle Anweisungen

break -, continue -Anweisung

i = 0;for (;;) {

i++;if (i == 17) break;i++;

}

i = 0;while (++i < 16) {

func1 (i);if (i < 8) continue;func2 (i);

}

return -Anweisung

return (i);

goto -Anweisung

goto STORAGE_ERROR;/* ... */

STORAGE_ERROR:fprintf (stderr, "zu wenig Speicher");exit (1);

leere Anweisung

;

Einführung in CDirk Husung

Spezielle Anweisungen (1)

Page 31: Documentc

TUHHRechenzentrum

3.5 Beispielprogramme

Zeichenkette kopieren

char achSrc [] = "Zeichenkette";char achDest [20];char * pchSrc = achSrc;char * pchDest = achDest;

int i = 0;

while ((pchDest[i] = pchSrc[i]) != 0)i++;

oder:

while ((*pchDest = *pchSrc) != 0) {pchDest++;pchSrc++;

}

oder:

while ((*pchDest++ = *pchSrc++) != 0);

oder:

while (*pchDest++ = *pchSrc++);

Einführung in CDirk Husung

Beispielprogramme (1)

Page 32: Documentc

TUHHRechenzentrum

/******************************************** cel2fahr: Celsius-Fahrenheit-Tabelle********************************************/

#include <stdio.h>

int main (void){

double dCel;

printf ("Celsius Fahrenheit\n");

for (dCel = 300; dCel >= 0; dCel -= 20)printf ("%6.0f %6.1f\n",

dCel, (dCel*9)/5 + 32);

return (0);} /* main */

Einführung in CDirk Husung

Beispielprogramme (2)

Page 33: Documentc

TUHHRechenzentrum

/******************************************** wc: Zeichen, Woerter, Zeilen zaehlen.********************************************/

#include <stdio.h>

#define FALSE 0#define TRUE 1

int main (void){

int nChars = 0;int nWords = 0;int nLines = 0;int fInWord = FALSE;int c; /* eingelesenes Zeichen */

while ((c = getchar()) != EOF) {++nChars;if (c == ’\n’)

++nLines;if (c == ’ ’ || c == ’\n’ || c == ’\t’)

fInWord = FALSE;else if (fInWord == FALSE) {

fInWord = TRUE;++nWords;

}} /* while */

printf("%d Zeichen, %d Woerter, %d Zeilen\n",nChars, nWords, nLines);

return (0);} /* main */

Einführung in CDirk Husung

Beispielprogramme (3)

Page 34: Documentc

TUHHRechenzentrum

/******************************************** dos2unix: <CR,LF> durch <LF> ersetzen.********************************************/

#include <stdio.h>

#define CR 0x0D#define LF 0x0A

int main (void){

int c;

while ((c = getc (stdin)) != EOF) {switch (c) {

case CR :do {

if ((c = getc (stdin)) == LF)break;

putc (CR, stdout);if (c == EOF) goto ENDWHILE;

} while (c == CR);/* kein break */

default :putc (c, stdout);break;

}} ENDWHILE:

return (0);} /* main */

Einführung in CDirk Husung

Beispielprogramme (4)

Page 35: Documentc

TUHHRechenzentrum

/******************************************** unix2dos: <LF> durch <CR,LF> ersetzen.********************************************/

#include <stdio.h>

#define CR 0x0D#define LF 0x0A

int main (void){

int c;

while ((c = getc (stdin)) != EOF) {switch (c) {

case CR :do {

putc (CR, stdout);} while ((c = getc (stdin)) == CR);if (c == EOF) goto ENDWHILE;

putc (c, stdout);break;

case LF :putc (CR, stdout);

default :putc (c, stdout);

}} ENDWHILE:

return (0);} /* main */

Einführung in CDirk Husung

Beispielprogramme (5)

Page 36: Documentc

TUHHRechenzentrum

/******************************************** tabexp: Tabulatorzeichen expandieren.********************************************/

#include <stdio.h>

#define TABWIDTH 8

int main (void){

int iColumn;int c;

iColumn = 0;while ((c = getc (stdin)) != EOF) {

switch (c) {case ’\t’ :

do {putc (’ ’, stdout);

} while (++iColumn % TABWIDTH);break;

case ’\n’ :putc (’\n’, stdout); iColumn = 0;break;

default :putc (c, stdout); iColumn++;break;

} /* switch */} /* while */

return (0);} /* main */

Einführung in CDirk Husung

Beispielprogramme (6)

Page 37: Documentc

TUHHRechenzentrum

4 Höhere Datentypen

4.1 Benutzerdefinierte Datentypen

Komplexere Vereinbarungen lassen sich schritt-weise lesen, wenn die durch Klammerung und Prio-ritäten vorgegebene Reihenfolge beachtet wird; mit

(term)[] „Feld von“(term)() „Funktion mit Wert“*(term) „Zeiger auf“

beispielsweise:

int *x[8]; Feld von 8 Zeigern auf int

int *x(int); Funktion mit Wert Zeiger auf int

int (*x)[]; Zeiger auf Feld von int

int (*x)(int); Zeiger auf Funktion mit Wert int

wichtig:

In der Definition:

int * a, b;

wird a als Zeiger auf int , b jedoch lediglich alsint erklärt!

Einführung in CDirk Husung

Benutzerdefinierte Datentypen (1)

Page 38: Documentc

TUHHRechenzentrum

Abhilfe: benutzerdefinierte Typen

Typdefinitionen:

#define VOID voidtypedef VOID * PVOID;

#define INT inttypedef INT * PINT;typedef PINT * PPINT;

#define SIZE size_t; /* aus stdlib.h */typedef SIZE * PSIZE;typedef PSIZE * PPSIZE;

typedef INT FINT (INT);typedef FINT * PFINT;

damit:

PINT x [8];PINT x (INT);PPINT x;PFINT x;

Einführung in CDirk Husung

Benutzerdefinierte Datentypen (2)

Page 39: Documentc

TUHHRechenzentrum

4.2 Mehrdimensionale Felder

statische Felder

INT IntMatrix [2][4] = {{1, 2, 3, 4},{5, 6, 7, 8}

};

IntMatrix [0][0] = 0;

• Allokierung eines zusammenhängenden Spei-cherbereichs fester Dimension.

• zeilenweise Speicherung einer Matrix.

• der letzte Index bezieht sich auf ein Elementvom Grundtyp.

Einführung in CDirk Husung

Mehrdimensionale Felder (1)

Page 40: Documentc

TUHHRechenzentrum

dynamische Felder

Mat

Mat[3]

Mat[2]

Mat[1]

Mat[0]

Mat[3][0]

Mat[2][0] Mat[2][1]

Mat[1][0] Mat[1][1] Mat[1][2]

Mat[0][0] Mat[0][1] Mat[0][2] Mat[0][3]- -

-

-

-

#define NROWS 4

PPINT ppIntMatrix;SIZE i;

ppIntMatrix = (PPINT) malloc (NROWS * sizeof (PINT));

for (i = 0; i < NROWS; i++) {SIZE uSize = (NROWS - i) * sizeof (INT);

ppIntMatrix [i] = (PINT) malloc (uSize);memset (ppIntMatrix [i], 0, uSize);

}

ppIntMatrix [0][0] = 1;

Einführung in CDirk Husung

Mehrdimensionale Felder (2)

Page 41: Documentc

TUHHRechenzentrum

4.3 Strukturen und Varianten

Strukturen

typedef struct _NODE {INT Elmt;struct _NODE *Next;

} NODE;

typedef NODE * PNODE;

NODE Node;PNODE pNode = & Node;

Node.Elmt = 1;(*pNode).Elmt = 1;pNode -> Elmt = 1;

Varianten (der Speicherbereich einer jeden Kom-ponente beginnt an derselben Adresse)

typedef union {DOUBLE x;UCHAR c [8];

} CONV;

CONV d;

d.x = 1.2;d.c[7] = -d.c[7];

Einführung in CDirk Husung

Strukturen und Varianten (1)

Page 42: Documentc

TUHHRechenzentrum

Operationen auf Strukturen

• Adresse einer Struktur bestimmen („&“-Operator)

• Zugriff auf Komponenten einer Struktur („. “- und„-> “-Operator)

• Größe einer Struktur bestimmen(sizeof -Operator)

• Zuweisung als GanzesDies beinhaltet Argumentübergabe und Ergeb-nisrückgabe eines Funktionsaufrufs (per Wert).In der Regel ist die Übergabe bzw. Rückgabeeines Zeigers auf eine Struktur effizienter! (Inälteren K&R-C Versionen steht die Zuweisungvon Strukturen nicht zur Verfügung; hier Zuwei-sung mit memcpy() .)

• Strukturen können nicht mit Vergleichsoperato-ren verglichen werden (Vergleich auf Gleichheitmit memcmp().)

Einführung in CDirk Husung

Strukturen und Varianten (2)

Page 43: Documentc

TUHHRechenzentrum

4.4 Aufzählungstyp, Bitfelder

Aufzählungstyp

typedef enum {FALSE, TRUE, OFF = 0, ON

} BOOLEAN;

Bit-Felder

typedef struct {unsigned Day : 5; /* Bits 0..4 */unsigned Month : 4; /* Bits 5..8 */unsigned Year : 7; /* Bits 9..15 */

} DATE;

Einführung in CDirk Husung

Aufzählungstyp, Bitfelder (1)

Page 44: Documentc

TUHHRechenzentrum

5 Funktionen

Eine Funktion wird deklariert (Funktionsprototyp) inder Form

[extern ] [Ergebnistyp] Funktionsname ( [Parameterliste]);

oder:

static [Ergebnistyp] Funktionsname ( [Parameterliste]);

Eine Funktion wird definiert in der Form

[static ] [Ergebnistyp] Funktionsname ( [Parameterliste]){

definitionsstatements

}

Darin sind die Parameter einer Parameterliste durchKommata getrennt anzugeben in der Form einerVariablendefintion (ohne Initialisierung).

In der Funktionsdeklaration kann die Angabe einesParameternamens entfallen.

Einführung in CDirk Husung

Funktionen (1)

Page 45: Documentc

TUHHRechenzentrum

• Eine Funktion ist vor ihrer Benutzung zu dekla-rieren.

• Eine Funktion ist standardmäßig programmweitab ihrer Deklaration sichtbar.

• Eine als static vereinbarte Funktion ist ab ih-rer Deklaration modulweit sichtbar.

• Eine Funktion eines anderen Moduls sollte alsextern deklariert werden.

• Die Definition einer Funktion kann ihre Deklara-tion ersetzen.

• Eine Prozedur (ohne Ergebnistyp) kann alsFunktion mit dem Ergebnistyp void vereinbartwerden.

• Fehlt die Angabe des Ergebnistyps, so gilt derErgebnistyp int als vereinbart.

• Einer aufrufenden Funktion ist es freigestellt,das Ergebnis einer aufgerufenen Funktion zuverwenden oder nicht.

• Eine parameterlose Funktion ist als Funktion mitder Parameterliste (void) zu vereinbaren.

• Argumente werden stets per Wert übergeben.

• Funktionen können rekursiv aufgerufen werden.

Einführung in CDirk Husung

Funktionen (2)

Page 46: Documentc

TUHHRechenzentrum

5.1 Beispiel: Konvertierung

Zeichenkette → ganze Zahl

#include <ctype.h>

int atoi (char * pszNumber){

int iNumber = 0;int iSign;

while (isspace (*pszNumber))pszNumber++;

iSign = (*pszNumber == ’-’) ? -1 : 1;if (*pszNumber == ’-’ || *pszNumber == ’+’)

pszNumber++;

while (isdigit (*pszNumber))iNumber =

iNumber * 10 + (*pszNumber++ - ’0’);

return (iSign * iNumber);} /* atoi */

Einführung in CDirk Husung

Konvertierung: Zeichenkette→ ganze Zahl (1)

Page 47: Documentc

TUHHRechenzentrum

5.2 Argumentübergabe per Wert

so nicht:

void Swap (int a, int b){

int t = a;

a = b; b = t;} /* Swap */

sondern so:

void Swap (int * pa, int * pb){

int t = *pa;

*pa = *pb; *pb = t;} /* Swap */

alternativ:

#define Swap(a, b) { \int t = a; \a = b; b = t; \

}

Einführung in CDirk Husung

Argumentübergabe per Wert (1)

Page 48: Documentc

TUHHRechenzentrum

5.3 Rekursiver Aufruf von Funktionen

int fac (int n){

if (n <= 1)return (1);

elsereturn (n*fac(n-1));

} /* fac */

_fac:push ebpmov ebp, esp

cmp [ebp+8],1jg L1

mov eax,1jmp L2

L1:mov eax,[ebp+8]dec eaxpush eaxcall _facadd esp, 4imul eax, [ebp+8]

L2:mov esp, ebppop ebpret

0x1001C:0x10018:0x10014: 8

0x10010: ret-addr

0x1000C: bp ← sp

0x10008:0x10004:0x10000:

Einführung in CDirk Husung

Rekursiver Aufruf von Funktionen (1)

Page 49: Documentc

TUHHRechenzentrum

5.4 Argumente der main -Funktion

Mögliche Definitionsformen der main -Funktion:

Ohne Berücksichtigung von Aufrufargumenten:

int main (void){

...}

Mit Zugriff auf Argumente bei Programmaufruf:

int main (int nArgs, char* aArg[]){

...}

Dabei liefert:aArg[0] den Namen des aufgerufenen Programms.aArg[1] . . . Zeiger auf Aufrufargumente.aArg[nArgs] den Wert NULL.

Mit zusätzlichem Zugriff auf Umgebungsvariablen:

int main (int nArgs, char* aArg[],char* pEnv[])

{...

}

Der letzte Eintrag von pEnv besitzt den Wert NULL.

Einführung in CDirk Husung

Argumente der main -Funktion (1)

Page 50: Documentc

TUHHRechenzentrum

5.5 Variable Parameteranzahl

#include <stdarg.h>

void ErrorMsg (int iLine, int iCol, int iErrorClass, ... )

{va_list Argument; /* fuer va_...-Macros */

va_start (Argument, iErrorClass);switch (iErrorClass) {

case eReservedSym:/* ... */break;

case eUnknownFunc: {char * pchText = va_arg (

Argument, char *);

/* ... */vprintf (pchText, Argument);

} break;}va_end (Argument);

} /* ErrorMsg */

Einführung in CDirk Husung

Variable Parameteranzahl (1)

Page 51: Documentc

TUHHRechenzentrum

5.6 Unterschiede: ANSI-C — K&R-C

ANSI-C mit Funktionsprototyp:

double CylinderVolume (double rad, double height);

double CylinderVolume (double rad, double height)

{return (height*rad*rad*3.14159);

} /* CylinderVolume */

Aufruf:

CylinderVolume (1, 2);

→ implizite Typanpassung!

oder K&R-C:

double CylinderVolume ();

double CylinderVolume (rad, height)double rad, height;

{return (height*rad*rad*3.14159);

} /* CylinderVolume */

Aufruf:

CylinderVolume (1, 2);

→ Laufzeitfehler!

Einführung in CDirk Husung

Unterschiede: ANSI-C — K&R-C (1)

Page 52: Documentc

TUHHRechenzentrum

6 Beispiele

6.1 Taschenrechner

# -----------------------------------------# Makefile (dmake): Taschenrechner# -----------------------------------------

CC = gccCFLAGS = -Wall -O2 # alle Warnungen,

# Optimierungen

OBJS = calc.o scanner.o stack.o

# ---- Programme --------------------------

calc.exe: $(OBJS)$(CC) $(OBJS) -o calc.exe

# ---- Abhaengigkeiten --------------------

calc.o: calc.ccalc.o: scanner.hcalc.o: stack.h

scanner.o: scanner.c scanner.h

stack.o: stack.c stack.h

# ---- Regeln -----------------------------

.o: .c$(CC) -c $(CFLAGS) $< -o $@

Einführung in CDirk Husung

Taschenrechner (1)

Page 53: Documentc

TUHHRechenzentrum

/******************************************* calc.c: einfacher Taschenrechner*******************************************/

#include <stdio.h>#include <math.h>

#include "scanner.h"#include "stack.h"

#define loop for(;;)

/******************************************* Konstanten-Definitionen*******************************************/

#define TOKENSIZE 256

/******************************************* Hauptprogramm*******************************************/

int main (void){

/* ... */} /* main */

Einführung in CDirk Husung

Taschenrechner (2)

Page 54: Documentc

TUHHRechenzentrum

int main (void){

char achToken [TOKENSIZE];

loop {switch (GetToken (achToken)) {

case NUMBER:Push (atof (achToken));break;

case ’+’:Push (Pop () + Pop ());break;

case ’-’: {double dOp = Pop ();Push (Pop () - dOp);

} break;case ’*’:

Push (Pop () * Pop ());break;

case ’/’: {double dOp = Pop ();if (dOp == 0)

printf ("division by zero\n");Push (Pop () / dOp);

} break;case ’\n’:

printf ("%g\n", Pop ());break;

case EOF:return (0);

default:printf ("unknown command %s\n",

achToken);break;

}} /* loop */

} /* main */

Einführung in CDirk Husung

Taschenrechner (3)

Page 55: Documentc

TUHHRechenzentrum

/******************************************* scanner.h: Scanner*******************************************/

#ifndef __SCANNER__#define __SCANNER__

/******************************************* Konstanten-Definitionen*******************************************/

#define NUMBER 256

/******************************************* Funktions-Prototypen*******************************************/

extern int GetToken (char * pchToken);

#endif

/******************************************* scanner.c: Scanner*******************************************/

#include <stdio.h>#include <ctype.h>#include "scanner.h"

/******************************************* Implementierung globaler Funktionen*******************************************/

int GetToken (char * pchToken){

/* ... */} /* GetToken */

Einführung in CDirk Husung

Taschenrechner (4)

Page 56: Documentc

TUHHRechenzentrum

int GetToken (char * pchToken){

int c;

/* Zwischenraumzeichen ueberlesen */ {while ((c = getc (stdin)) == ’ ’

|| c == ’\t’);

}

/* ggf. Zahl einlesen */ {if (isdigit (c) || c == ’.’) {

if (isdigit (c))do {

*pchToken++ = c;} while (isdigit (c = getc (stdin)));

if (c == ’.’)do {

*pchToken++ = c;} while (isdigit (c = getc (stdin)));

*pchToken = 0;ungetc (c, stdin);return (NUMBER);

}}

/* sonstige Zeichen */ {*pchToken++ = c;*pchToken = 0;return (c);

}} /* GetToken */

Einführung in CDirk Husung

Taschenrechner (5)

Page 57: Documentc

TUHHRechenzentrum

/******************************************* stack.h: double-Stack*******************************************/

#ifndef __STACK__#define __STACK__

/******************************************* Funktions-Prototypen*******************************************/

extern void Push (double dValue);extern double Pop (void);

#endif

Einführung in CDirk Husung

Taschenrechner (6)

Page 58: Documentc

TUHHRechenzentrum

/******************************************* stack.c: double-Stack*******************************************/

#include <stdio.h>#include "stack.h"

/******************************************* Konstanten- und Variablen-Definitionen*******************************************/

#define STACKSIZE 32

static double aStack [STACKSIZE];static int iStack = 0;

/******************************************* Implementierung globaler Funktionen*******************************************/

void Push (double dValue){

if (iStack == STACKSIZE)printf ("stack overflow\n");

elseaStack [iStack++] = dValue;

} /* Push */

double Pop (void){

if (iStack)return (aStack [--iStack]);

else {printf ("stack underflow\n");return (0.0);

}} /* Pop */

Einführung in CDirk Husung

Taschenrechner (7)

Page 59: Documentc

TUHHRechenzentrum

6.2 Portabilität

/******************************************* Portab.h Spracherweiterungen,* Maschinenabhaengigkeiten*******************************************/

#ifndef __PORTAB__#define __PORTAB__

#include <stdlib.h>

#if defined (__GNUC__)#define __ANSI__#ifndef __32BIT__#define __32BIT__#endif#define __LOWBYTEFIRST__#endif

#if defined (__XLC__)#define __32BIT__#define __HIGHBYTEFIRST__#endif

#if defined (__STDC__) ||\defined (__ANSI__) ||\defined (__cplusplus)

#define ARGS(parameters) parameters#define NOARGS VOID#else#define ARGS(parameters) ()#define NOARGS#endif

Einführung in CDirk Husung

Portabilität (1)

Page 60: Documentc

TUHHRechenzentrum

/******************************************* Konstantendefinitionen*******************************************/

#define TRUE 1#define FALSE 0

#define SUCCESS 0#define FAILURE (-1)

#if defined (__LOWBYTEFIRST__)#define LO 0#define HI 1#elif defined (__HIGHBYTEFIRST__)#define LO 1#define HI 0#else#error byte order undefined!#endif

/******************************************* Verschiedenes*******************************************/

#if !defined (NULL)#define NULL 0L#endif

#define loop for (;;)#define sqr(a) ((a)*(a))#define min(a,b) (((a) < (b)) ? (a) : (b))#define max(a,b) (((a) > (b)) ? (a) : (b))#define dimof(array)\

(sizeof(array) / sizeof(*(array)))

#endif /* !__PORTAB__ */

Einführung in CDirk Husung

Portabilität (2)

Page 61: Documentc

TUHHRechenzentrum

6.3 Dynamische Speicherverwaltung

/******************************************* DynMem.h*******************************************/

#ifndef __DYNMEM__#define __DYNMEM__

extern PVOID _MemNew ARGS ((SIZE uSize));/***************************************** Funktion : Allokiert uSize Bytes* Speicher.* Eingaben : uSize: Groesse des Speicher-* bereichs.* Ergebnis : Zeiger auf Speicherbereich.* Annahmen : uSize ist ohne Rest durch 4* teilbar.*/

extern VOID _MemDelete ARGS ((PVOID pMemory, SIZE uSize));/***************************************** Funktion : Gibt einen mit _MemNew()* allokierten Speicherbereich* frei.* Eingaben : pMemory: Zeiger auf freizu-* gebenden Speicher-* bereich.* uSize : Groesse des* Speicherbereichs.* Annahmen : uSize ist ohne Rest durch 4* teilbar.*/

#endif /* !__DYNMEM__ */

Einführung in CDirk Husung

Dynamische Speicherverwaltung (1)

Page 62: Documentc

TUHHRechenzentrum

/******************************************* DynMem.c*******************************************/

#include "Portab.h"#include "DynMem.h"

PVOID _MemNew (SIZE uSize){

PPVOID pMemory;

if (uSize <= MEM_MAXSIZE&& (pMemory = (PPVOID) *((PPVOID)((PCHAR) MemStore + uSize))) != NULL) {

*((PPVOID) ((PCHAR) MemStore + uSize)) =*pMemory;

}else if ((pMemory = (PPVOID) malloc (

uSize)) == NULL) {INT iErrorClass = 0;

do {(*MemErrorHandler) (iErrorClass++);

} while ((pMemory = (PPVOID) malloc (uSize)) == NULL);

}#if defined (__MEMTEST__)

ulMemUsed += uSize;if (ulMemUsed > ulMaxMemUsed)

ulMaxMemUsed = ulMemUsed;#endif#if defined (__PROTOCOL__)

printf ("MemNew: %p (%d Bytes)\n",pMemory, uSize);

#endifreturn (PVOID) pMemory;

} /* _MemNew */

Einführung in CDirk Husung

Dynamische Speicherverwaltung (2)

Page 63: Documentc

TUHHRechenzentrum

VOID _MemDelete (PVOID pMemory, SIZE uSize){

if (uSize <= MEM_MAXSIZE) {*((PPVOID) pMemory) =*((PPVOID) ((PCHAR) MemStore + uSize));*((PPVOID) ((PCHAR) MemStore + uSize)) =

pMemory;}else

free ((PCHAR) pMemory);#if defined (__MEMTEST__)

ulMemUsed -= uSize;#endif#if defined (__PROTOCOL__)

printf ("MemDelete: %p (%d Bytes)\n",pMemory, uSize);

#endif} /* _MemDelete */

Einführung in CDirk Husung

Dynamische Speicherverwaltung (3)

Page 64: Documentc

TUHHRechenzentrum

6.4 Automatische Differentiation

Mit Hilfe der „automatischen Differentiation“ ist diedirekte numerische Berechnung des Wertes einerFunktion und des Wertes ihrer (ersten) Ableitungan einer gegebenen Stelle möglich.

Dazu kann ähnlich den komplexen Zahlen ein TypGRADIENTals Zahlenpaar F = (f(x), f ′(x))|x=x0

erklärt werden mit folgenden Eigenschaften:

F = G+H : (f(x), f ′(x))|x=x0

= ((g + h)(x), (g + h)′(x))|x=x0

= (g(x) + h(x), g′(x) + h′(x))|x=x0

analog für −, ·, /

F = G◦H : (f(x), f ′(x))|x=x0

= (g(h(x)), g′(h(x)) · h′(x))|x=x0

F = c : (f(x), f ′(x))|x=x0

= (c, 0)

F = x : (f(x), f ′(x))|x=x0

= (x0, 1)

Einführung in CDirk Husung

Automatische Differentiation (1)

Page 65: Documentc

TUHHRechenzentrum

/******************************************* Gradient.h: Automatische Differentiation*******************************************/

#ifndef __GRADIENT__#define __GRADIENT__

#include <stdio.h>#include <math.h>

typedef struct {DOUBLE x; /* Wert */DOUBLE dx; /* Wert der 1. Ableitung */

} GRADIENT;

typedef GRADIENT * PGRADIENT;

GRADIENT Const (DOUBLE d);GRADIENT Deriv (DOUBLE d);

GRADIENT Add (GRADIENT a, GRADIENT b);GRADIENT Sub (GRADIENT a, GRADIENT b);GRADIENT Mul (GRADIENT a, GRADIENT b);GRADIENT Div (GRADIENT a, GRADIENT b);

GRADIENT Exp (GRADIENT a);GRADIENT Sin (GRADIENT a);GRADIENT Cos (GRADIENT a);

#endif /* !__GRADIENT__ */

Einführung in CDirk Husung

Automatische Differentiation (2)

Page 66: Documentc

TUHHRechenzentrum

/******************************************* Gradient.c: Automatische Differentiation*******************************************/

#include "Portab.h"#include "Gradient.h"

GRADIENT Const (DOUBLE d){

GRADIENT r;

r.x = d;r.dx = 0.0;

return (r);} /* Const */

GRADIENT Deriv (DOUBLE d){

GRADIENT r;

r.x = d;r.dx = 1.0;

return (r);} /* Deriv */

GRADIENT Add (GRADIENT a, GRADIENT b)/* (a, a’) + (b, b’) = (a+b, a’+b’) */

{GRADIENT r;

r.x = a.x + b.x;r.dx = a.dx + b.dx;

return (r);} /* Add */

Einführung in CDirk Husung

Automatische Differentiation (3)

Page 67: Documentc

TUHHRechenzentrum

/* todo: Sub */

GRADIENT Mul (GRADIENT a, GRADIENT b)/* (a, a’) * (b, b’) = (a*b, a’*b+a*b’) */

{GRADIENT r;

r.x = a.x * b.x;r.dx = a.dx * b.x + a.x * b.dx;

return (r);} /* Mul */

/* todo: Div */

GRADIENT Exp (GRADIENT a)/* exp (a, a’) = (exp(a), exp(a) * a’) */

{GRADIENT r;

r.x = exp (a.x);r.dx = exp (a.x) * a.dx;

return (r);} /* Exp */

GRADIENT Sin (GRADIENT a)/* sin (a, a’) = (sin(a), cos(a) * a’) */

{GRADIENT r;

r.x = sin (a.x);r.dx = cos (a.x) * a.dx;

return (r);} /* Sin */

/* todo: Cos */

Einführung in CDirk Husung

Automatische Differentiation (4)

Page 68: Documentc

TUHHRechenzentrum

#if defined (__MAIN__)

INT main (VOID)/* Test: f(x ) = x + exp (sin (2*x)) */

{DOUBLE d;

for (d = 0; d < 3; d += 0.25) {GRADIENT x = Deriv (d);GRADIENT fx = Add (x,

Exp (Sin (Mul (Const (2), x))));

printf ("f(%4.2f) = %11.8f, ""f’(%4.2f) = %11.8f\n",d, fx.x, d, fx.dx);

}

return (0);} /* main */

#endif /* __MAIN__ */

Einführung in CDirk Husung

Automatische Differentiation (5)

Page 69: Documentc

TUHHRechenzentrum

6.5 Aufruf von Fortran-Routinen aus C

Die Kopplung von f77- und C-Routinen ist z.B.dann von Bedeutung, wenn man Programmbiblio-theken, die in Fortran geschrieben sind (z.B. dieNAG-Bibliothek), von C aus benutzen möchte.

Die Form eines solchen Aufrufs ist jedoch compi-lerabhängig!

Allgemeine Hinweise:

• Unterprogrammnamen

cc- und f77-Compiler von HP verwenden glei-che Namenskonventionen.

(Einige Fortran-Compiler hängen beim Überset-zen jeweils einen Unterstrich an die Routinena-men an. Beim Aufruf einer f77-Routine von Caus muß dann dieser Unterstrich angefügt wer-den.)

• Datentypen

Es gibt folgende Korrespondenzen bei den wich-tigsten Typen:

Einführung in CDirk Husung

Aufruf von Fortran-Routinen aus C (1)

Page 70: Documentc

TUHHRechenzentrum

FORTRAN C

INTEGER i long int i;

REAL x float x;

DOUBLE PRECISION s double s;

COMPLEX*8 z struct {float re, im;} z;

COMPLEX*16 w struct {double r, i; } w;

CHARACTER*6 c char c[6];

• Argumentübergabe

In Fortran werden Argument stets „by refe-rence“ übergeben. Hierbei erhält das aufgerufe-ne Unterprogramm die Adresse der übergebe-nen Variable.

In C hingegen werden Argumente stets „by va-lue“ übergeben. Das Unterprogramm erhält nureine Kopie mit dem aktuellen Wert des Argu-ments, kann so jedoch nicht den Argumentwertselbst verändern (hierzu müßte die Adresse be-kannt sein).

Um in C Adressen zu übergeben, benutzt manden Operator „&“ vor dem Variablennamen.

FORTRAN C

INTEGER a, b, sum int a, b, sum;

call add (a, b, sum) add (&a, &b, &sum);

Einführung in CDirk Husung

Aufruf von Fortran-Routinen aus C (2)

Page 71: Documentc

TUHHRechenzentrum

CHARACTER-Datentypen aus f77 entsprechenFeldern in C; die Länge des Feldes muß jedochin C zusätzlich als ein long int übergebenwerden.

FORTRAN C

CHARACTER*5 sss char sss[5];

CHARACTER*8 tt char tt[8];

call sub (sss, tt) sub (sss, tt, 5L, 8L);

Bei der Übergabe mehrdimensionaler Felder istVorsicht geboten, da diese in f77 spaltenweise,in C hingegen zeilenweise gespeichert werden.

Die Übergabe von Funktionen in der Argument-liste wird weiter unten an einem Beispiel de-monstriert.

• Ein-/Ausgabe

Fortran und C benutzen ein unterschiedlichesEin-/ Ausgabesystem. Daher kann es zu Pro-blemen führen, wenn sowohl von C als auch vonFortran aus Ein- oder Ausgaben vorgenommenwerden sollen.

Einführung in CDirk Husung

Aufruf von Fortran-Routinen aus C (3)

Page 72: Documentc

TUHHRechenzentrum

Beispiel:

/******************************************* C-Programm: fprog1.c*******************************************/

#include <stdio.h>

#if defined (HP)#define SUBROUTINE(Name) Name#elif defined (CONVEX)#define SUBROUTINE(Name) Name_#endif

float fkt (float *x);

void SUBROUTINE(fkt_uebergabe) (float *x, float (*f)(float *), float *y);

int main(void){

float x=2.0; float y=0.0;

printf ("\n Funktionsname als Argument:\n");SUBROUTINE(fkt_uebergabe) (&x, fkt, &y);printf (" x= %g, fkt(x) = %g\n", x, y);return (0);

}

/******************************************* C-Programm: fprog2.c*******************************************/

float fkt(float *x){

return(2.0* *x);}

Einführung in CDirk Husung

Aufruf von Fortran-Routinen aus C (4)

Page 73: Documentc

TUHHRechenzentrum

C -----------------------------------------C f77-Unterprogramm: fprog3.fC -----------------------------------------

subroutine fkt_uebergabe(x, f, y)external freal f, x, yy=f(x)end

Übersetzung auf hpxx und hydra mit:

cc -Aa -c -DHP fprog1.ccc -Aa -c fprog2.cf77 fprog1.o fprog2.o fprog3.f

Einführung in CDirk Husung

Aufruf von Fortran-Routinen aus C (5)

Page 74: Documentc

TUHHRechenzentrum

6.6 Tcl/Tk und C

Zu Tcl und Tk

Variablen:

set a 1set b a+2set c [expr $a+2]unset a

set Umsatz(Jan) 87966set Umsatz(Feb) 95400

set GesamtUmsatz 0foreach Monat {Jan Feb} {

incr GesamtUmsatz $Umsatz($Monat)}return $GesamtUmsatz

Ausdrücke:

expr 24/3.2lindex {rot gelb blau lila} 2string length "Dies ist ein Test"

Substitutionen:

• Variablenersetzung

• Befehlsersetzung

• Backslash-Substitution

Einführung in CDirk Husung

Tcl/Tk und C (1)

Page 75: Documentc

TUHHRechenzentrum

Kontrollstrukturen:

evalexprifelseifswitchforforeachwhile

Prozeduren:

proc Potenz {Basis Exponent} {set Ergebnis 1while {$Exponent > 0} {

set Ergebnis [expr $Ergebnis*$Basis]set Exponent [expr $Exponent-1]

}return $Ergebnis

}

Innerhalb einer Prozedur sind alle Variablen lokal.

Einführung in CDirk Husung

Tcl/Tk und C (2)

Page 76: Documentc

TUHHRechenzentrum

Beispiele

Hello, World:

#!/usr/local/bin/wish -fbutton .b -text "Hello, world!" -command exitpack .b

Potenzberechnung:

#!/usr/local/bin/wish -fproc Potenz {Basis Exponent} {

set Ergebnis 1while {$Exponent > 0} {

set Ergebnis [expr $Ergebnis*$Basis]set Exponent [expr $Exponent-1]

}return $Ergebnis

}entry .basis -width 6 -relief sunken\

-textvariable Basislabel .label1 -text "ist in der"entry .exponent -width 6 -relief sunken\

-textvariable Exponentlabel .label2 -text ". Potenz"label .ergebnis -textvariable Ergebnispack .basis .label1 .exponent .label2\

.ergebnis -side left -padx 1m -pady 2mbind .basis <Return> {

set Ergebnis [Potenz $Basis $Exponent]}bind .exponent <Return> {

set Ergebnis [Potenz $Basis $Exponent]}

Einführung in CDirk Husung

Tcl/Tk und C (1)

Page 77: Documentc

TUHHRechenzentrum

Tcl/Tk und C:

/********************************************* $Id: draw.c Tcl/Tk-Beispiel*********************************************/

#include <stdio.h>#include <tcl.h>#include <tk.h>

/********************************************* Variablen-Definitionen*********************************************/

static Tcl_Interp * interp;

/********************************************* Prototypen lokaler Funktionen*********************************************/

static void tcltkInit (int nArgs, char * aArg []);

static void tcltkTerm (void);

static int drawLine (int x0, int y0, int x1, int y1);

/********************************************* Implementierung lokaler Funktionen*********************************************/

static void tcltkInit (int nArgs,char * aArg [])

{char * pArg;char ach [16];

Einführung in CDirk Husung

Tcl/Tk und C (2)

Page 78: Documentc

TUHHRechenzentrum

Tcl_FindExecutable (aArg [0]);interp = Tcl_CreateInterp ();

pArg = Tcl_Merge (nArgs-1, aArg+1);Tcl_SetVar (interp,

"argv", pArg, TCL_GLOBAL_ONLY);Tcl_Free (pArg);

sprintf (ach, "%d", nArgs-1);Tcl_SetVar (interp,

"argc", ach, TCL_GLOBAL_ONLY);Tcl_SetVar (interp,

"argv0", aArg [0], TCL_GLOBAL_ONLY);Tcl_SetVar (interp,

"tcl_interactive", "0", TCL_GLOBAL_ONLY);

if (Tcl_Init (interp) == TCL_ERROR) {fprintf (stderr, "Tcl_Init: %s\n",

interp -> result);exit (1);

}if (Tk_Init (interp) == TCL_ERROR) {

fprintf (stderr, "Tk_Init: %s\n",interp -> result);

exit (1);}Tcl_StaticPackage (interp,"Tk", Tk_Init, 0);

} /* tcltkInit */

static void tcltkTerm (void){

Tcl_DeleteInterp (interp);Tcl_Exit (0);

} /* tcltkTerm */

Einführung in CDirk Husung

Tcl/Tk und C (3)

Page 79: Documentc

TUHHRechenzentrum

static int drawLine (int x0, int y0, int x1, int y1) {

char command [64];

sprintf (command,".c create line %d %d %d %d",x0, y0, x1, y1);

return Tcl_Eval (interp, command);} /* drawLine */

/********************************************* Hauptprogramm*********************************************/

int main (int nArgs, char * aArg[]){

tcltkInit (nArgs, aArg);atexit (tcltkTerm);

Tcl_Eval (interp,"canvas .c -width 640 -height 480");

Tcl_Eval (interp, "pack .c");Tcl_Eval (interp,

"button .b -text \"Quit\" -command exit");Tcl_Eval (interp, "pack .b");Tcl_Eval (interp, "focus .c");

drawLine (10, 10, 200, 100);

while (Tcl_DoOneEvent (0));

return (0);} /* main */

Einführung in CDirk Husung

Tcl/Tk und C (4)