documentc
DESCRIPTION
cTRANSCRIPT
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)