Programmieren in C
Programmierkurs
Aufbau
1. Historisches und Grundlagen
Entwicklung von Computern
Prozessorarchitekturen
Programmiersprachen
Ein einfaches Programm
2. Rechnen, Bedingungen,
Schleifen
Operatoren
if…else…then
for
while – do…while
3. Zeichen, Zeichenketten,
Zeiger, Strukturen
Strings
Was ist ein Pointer?
Strukturen/Unions
Typen
19.08.2010 | FP 5 | Kernphysik | M. Platz | 2
4. Strukturiertes Programmieren
Symbolische Konstanten, Makros,
Header
ObjektDateien/Bibliotheken/Linker
5. Spezialitäten
Variable Argumentenliste
Dynamischer Speicher
Rekursion
Zeiger auf Funktionen
Tag 1
Historisches und Grundlagen
Entwicklung der Rechner
Rechenhilfen
Abacus
Rechenschieber …
Programmierbare Maschinen
Webstühle (1745)
Klavier…
Programmierbarer Rechner
Nutzung eines Zwischenergebnisses für weitere Rechenoperationen
Speicher
Rechnervarianten
Digital
Analog
19.08.2010 | FP 5 | Kernphysik | M. Platz | 4
Zuse Z1
Baujahr: 1937
Elektro-Mechanisch (Binär)
Ein-/Ausgabewerk
Rechenwerk
Speicherwerk
Programmwerk
Harvard-Architektur
19.08.2010 | FP 5 | Kernphysik | M. Platz | 5
Eniac
Baujahr: 1942
Röhren (Binär)
Rechnung im Dezimalsystem!
Kein Befehlsspeicher: Verkabelt
Später umgebaut auf von-Neumann-Architektur
19.08.2010 | FP 5 | Kernphysik | M. Platz | 6
Algebra
Bool‘sche Algebra
George Bool, englischer Mathematiker
Mathematical Analysis of Logic (1847)
Logik (Wahr/Falsch, 0/1)
Dual-System
Rechnen wie im Dezimalssystem
And:
1101
0011
0001
1101
0011
1111
Or:
8 4 2 1
+
1101 =13
0011 =3
10000
-
1101
0011
1010
19.08.2010 | FP 5 | Kernphysik | M. Platz | 7
1101
0011
Excl.Or: 1110
1101 * 0011
0000
0000
1101
1101
+
100111
1101
___________
Not:
0010
1101 : 0011 = 0100
0011
0011
-0000
0011
0011 + Rest 1
Grundlegender Aufbau einer CPU
Aufbau eines „typischen“ Computerprozessors (Z80 von Zilog)
Von-Neumann-Architektur
Recheneinheit (ALU)
Register
Adress-Bus
Instruction
Daten-Bus
Decoder
Data Bus
Interface
Instruction
Register
Data Bus
ALU
Register
Array
Address Bus
Address Logic
and Buffers
19.08.2010 | FP 5 | Kernphysik | M. Platz | 8
Register
Speicherstellen in der CPU
Schnellerer Zugriff als auf RAM über den Daten-/Adressbus
Teilweise bestimmte Funktionalität
A
F
A‘ F‘
B
C
B‘ C‘
D
E
D‘ E‘
H
L
H‘ L‘
IX
IY
SP
PC
I
19.08.2010 | FP 5 | Kernphysik | M. Platz | 9
R
Typisches Program
CD91BD
3F
C8
F20CA0
3E01
B7
C9
E5
1153A0
010500
EDB0
E1
…
NEWSQR CALL SGN
CCF
RET Z
JP P,GOON
LD A,1
OR A
RET
GOON PUSH HL
LD DE, STORE1
LD BC, 5
LDIR
POP HL
-> Hochsprache wünschenswert
19.08.2010 | FP 5 | Kernphysik | M. Platz | 10
Schnelle Funktion zum ziehen
der Quadratwurzel,
Brückmann, Englisch, Gerits, Steigers,
„CPC Intern“
Gängige Sprachen
Fortran (1954/1957, IBM)
BASIC (Beginner‘s All-Pupose Symbolic Instruction Code; 1964)
Pascal (1972, ETH Zürich, Lehrsprache)
C (Anfang 70er, Bell Labs, Unix)
C++ (Anfang 80er, AT&T)
Java (Anfang 90er, SUN)
19.08.2010 | FP 5 | Kernphysik | M. Platz | 11
Übersetzen einer Hochsprache
Interpreter
Schrittweise Syntax-Überprüfung, Übersetzung und Ausführung des
Programms (Scripte)
Compreter
Vollständige Syntax-Überprüfung und teilweise Übersetzung während der
Ausgabe, schrittweise endgültige Übersetzung während der Ausführung, oder
Schrittweise Syntax-Überprüfung und Übersetzung während der Ausführung,
wenn das Programm nicht mehr geändert wird, liegt es in Übersetzter Form
vor
Compiler
Syntax-Überprüfung und Übersetzung vor der Ausführung
19.08.2010 | FP 5 | Kernphysik | M. Platz | 12
Konventionen (Namen)
Namen (Variable)
Folge von Buchstaben und Ziffern
Erstes Zeichen Buchstabe (_ zählt als Buchstabe)
Beliebig lang
Die ersten 6 Zeichen werden unterschieden
Anmerkung:
Implementierungen dürfen auch mehr Zeichen als relevant betrachten
Interne Name sind umfassender
Wenigstens 31 Zeichen werden unterschieden
Case-Sensitiv
19.08.2010 | FP 5 | Kernphysik | M. Platz | 13
Konventionen (Schluesselworte)
Reservierte Worte (Schlüsselworte)
Anweisungen, Typen, Speicherklassen, Attribute
Sehr eingeschränkter Befehlssatz -> "Maschinennah"
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
19.08.2010 | FP 5 | Kernphysik | M. Platz | 14
Konventionen (Konstanten)
Konstanten
Ganzzahlige Konstanten
Zifferfolge (zunächst Dezimal)
Präfix 0x: Hexadezimal Æ 0xAF, 0Xaf
Präfix 0 (Null): Oktal Æ 072, 023
Suffix u: unsigned Æ 1234u
Suffix l: long Æ 12l
Zeichenkonstanten
Werden in einfachen Anführungszeichen (') angegeben Æ ('a')
Liefert den numerischen Wert des Zeichens im Zeichensatz der jeweiligen
Maschine, auf der das Programm ausgeführt wird
Möglich sind Definitionen von "wide character constants" (Präfix L)
Fliesskomma Konstanten
1000.50 ; 1.0/100.0 ; 10E20
Suffix f: float
Suffix l: long double
Aufzählungen
Ganzzahlige Konstanten (s. enum)
19.08.2010 | FP 5 | Kernphysik | M. Platz | 15
Konventionen (Strings)
Konstante Zeichenketten
Strings; Zeichenketten in Anführungszeichen ("…") angegeben
Statischer Vektor
Änderungsversuche undefiniert
NUL ('\0') Terminiert
Präfix L: wide character string
19.08.2010 | FP 5 | Kernphysik | M. Platz | 16
Konventionen (Operatoren)
Operatoren
Rechenoperationen, Zuweisung
Vergleiche
Bitmanipulation
Adressoperatoren
Sonstiges
+
-
*
++
/
--
%
==
&&
||
!
<
<=
>
>=
!=
|
<<
>>
~
&
^
&
*
?:
,
=
*=
+=
-=
/=
%=
<<=
>>=
&=
19.08.2010 | FP 5 | Kernphysik | M. Platz | 17
~=
|=
Syntax
#Präprozessoranweisung
Typ Name;
Typ Name=…;
Typ Name (Typ Name …)
{
Typ Name=…;
Typ Name, Name;
…
#
Präprozessoranweisung
Anweisung;
#
Präprozessoranweisung
Anweisung;
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 18
Präprozessoranweisungen können an
beliebigen Stellen stehen, # aber in
der ersten Spalte, kein ';' am Ende
der Zeile!
Blöcke strukturieren den Code
Deklarationen und Definitionen auf
allen Ebenen möglich, aber nur
innerhalb des Blocks gültig. Müssen
vor den ersten Anweisungen stehen.
Anweisungen, wie auch Deklarationen,
enden mit ';'
Hello World / Hinweise
#include <stdio.h>
#include <stdio.h>
#include <stdio.h>
main #include
()
<stdio.h>
main (void)
{ void #include
<stdio.h>
{ /* printf ("Hello World\n");
int main
main (int
(int argc
argc,[,char
char
{
int
char*argv,
*argv[]
[, *envp)
char *envp[]]])
printf
("Hello
World\n");
}
int main
(argc,
argv,
envp)
printf
("Hello
World\n");
} */
int argc;
return
1;
char *argv;
} main (int
int
argc, char *argv, char *envp)
char *envp;
{
{
printf ("Hello World\n");
printf ("Hello World\n");
return (1);
return 1;
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 19
Hello World
#include <stdio.h>
Präprozessor Befehl "Datei einbinden".
main ()
{
printf ("Hello World\n");
}
Hauptfunktion; Hier fängt die
Programmausführung an.
Diese Art der Definition
schaltet die Überprüfung der
Argumentenliste ab, es wird
kein Rückgabewert erwartet.
Funktionsaufruf; Deklaration in
"stdio.h" (Standardbibliothek).
19.08.2010 | FP 5 | Kernphysik | M. Platz | 20
Compilieren (Linux)
GNU C-Compiler (gcc):
benutzer@rechner:~$ gcc <C-File> -o <Ausgabedatei>
Genaue Überprüfung des C-Standards:
benutzer@rechner:~$ gcc –Wall <C-File> -o <Ausgabedatei>
hello_world.c:4: warning: return type defaults to 'int'
hello_world.c: In function 'main':
hello_world.c:6: warning: control reaches end of non-void function
19.08.2010 | FP 5 | Kernphysik | M. Platz | 21
Aufgaben
Versuchen, die Fehler zu entfernen
Mehrere
hintereinander
ausführen
printf,printf-Anweisungen
fprintf, sprintf, snprintf,
vprintf, vfprintf,
vsprintf, und die
vsnprintf - formatted output conversion
Ausgabe interpretieren.
SYNOPSIS
Benutzung
von<stdio.h>
Steuerzeichen (was bedeutet was?):
#include
\a, \b, \f,
\n, \r, \t, \v, \? ,\ooo,\xhhh
int printf(const char *format, ...);
fprintf(FILE\',
*stream,
Escape int
Sequenzen:
\",\\ const char *format, ...);
int sprintf(char *str, const char *format, ...);
int printf
snprintf(char
*str, size_t size, const char *format,
Mehr über
(benutzer@rechner:~$
man 3...);
printf)
#include <stdarg.h>
int
int
int
int
vprintf(const char *format, va_list ap);
vfprintf(FILE *stream, const char *format, va_list ap);
vsprintf(char *str, const char *format, va_list ap);
vsnprintf(char *str, size_t size, const char *format, va_list ap);
DESCRIPTION
19.08.2010 | FP 5 | Kernphysik | M. Platz | 22
Tag 2
Rechnen, Bedingungen, Schleifen
Rechnen
Addition
i = a + b;
i = i + x;
i += x;
Subtraktion
i = a – b;
i = i – x;
i -= x;
Multiplikation
i = a * b;
i = i * x;
i *= x;
Division
i = a / b;
i = i / x;
i /= x;
Inkrementieren
i = i + 1;
i += 1;
i ++;
++i;
Dekrementieren
i = i – 1;
i -= 1;
i --;
--i;
Modulo
i = a % b;
i = i % x;
i %= x;
19.08.2010 | FP 5 | Kernphysik | M. Platz | 24
Vergleiche
Alle Vergleiche geben einen Boolschen Wert zurück.
Der Typ BOOL ist in der Regel Betriebssystemabhängig und in
<stddef.h> definiert
Ist der Typ BOOL vorhanden, gibt es auch die symbolischen
Konstanten
FALSE
TRUE (! FALSE d.h alles ungleich FALSE)
Ist bei einem Vergleich Gleichheit festgestellt, ist das Ergebnis
TRUE, sonst FALSE
Für bedingte Code-Ausführung wird die if-else-Anweisung
benutzt
19.08.2010 | FP 5 | Kernphysik | M. Platz | 25
If-Else
#include <stdio.h>
main()
{
char c;
Bedingung
c = getchar(); {
if (c == ' '){
printf ("War ein SPACE\n");
}
else {
printf ("%c\n", c);
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 26
Ausführung
wenn TRUE
Ausführung
wenn FALSE
Vergleichsoperatoren
AND
&&
Ungleichheit
!=
OR
||
Größer
>
NOT
!
Kleiner
<
Größer Gleich
>=
Kleiner Gleich
<=
Gleichheit
==
19.08.2010 | FP 5 | Kernphysik | M. Platz | 27
Weitere Möglichkeit
Operator ?:
Bedingung
#include <stdio.h>
#include <stdio.h>
Zuweisung wenn
wahr
main()
{
if (a > b)
{
z = a;
}
else
{
z = b;
}
main()
{
z = (a > b) ? a : b;
}
Zuweisung wenn
falsch
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 28
Vorrang
#include <stdio.h>
main()
{
}
#include <stdio.h>
main()
if (y = a > b ||
{ a == 100 && b !=
{
if ((y = a
z = a;
{
}
z
else
}
{
else
z = b;
{
}
z
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 29
0)
> b) || ((a == 100) && (b != 0))
= a;
= b;
Schleifen
Wiederholung einer bestimmten Funktionalität
Kriterium für das Schleifenende
Anzahl der Durchläufe
Bestimmte Bedingungen sind erfüllt
Die Sprache C bietet zwei Schleifentypen
for-Schleife
In der Regel wird diese Schleife bei einer definierten Anzahl von
Durchläufen benutzt
while-Schleife bzw. do-while Kombination
Wird in der Regel für Schleifen benutzt, die durch Erfüllung von
Bedingungen beendet werden
Beide Schleifentypen sind prinzipiell austauschbar!
19.08.2010 | FP 5 | Kernphysik | M. Platz | 30
For-Schleife
/*
Umrechnung Fahrenheit in Celsius nach:
°C = (5/9)(F-32)
*/
#include <stdio.h>
Startwert
Abbruchkriterium
main()
{
unsigned int iF;
Operation nach einem
Schleifendurchgang
for (iF=0; iF<=300; iF = iF + 20)
{
printf ("%3d %6.1f\n", iF, (5.0/9.0)*(iF-32));
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 31
Intermezzo zu Variablen
Deklaration
Festlegen, um welchen Typ es sich handelt (kommt später)
Definition
Typ festlegen und Speicher reservieren
Initialisieren
Der definierten Variablen einen Wert zuweisen
{
{
int i; // Definition
int i = 0; /* Definition
und
Initialisierung*/
…
i = 0; // Initialisierung
…
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 32
}
Aufgaben (for-Schleife)
Was passiert, wenn die Schleifenvariable nicht initialisiert wird
Was passiert, wenn man (5.0/9.0) durch (5/9)
Was kann man bei der for-Schleife alles weglassen?
Kann die Schleifenvariable auch andere Typen haben (double,
long)?
19.08.2010 | FP 5 | Kernphysik | M. Platz | 33
While-Schleife
/*
Umrechnung Fahrenheit in Celsius nach:
°C = (5/9)(F-32)
*/
#include <stdio.h>
Abbruch Kriterium
main()
{
unsigned int iF = 0;
Initialisierung und
Inkrementierung an einer
anderen Stelle
while (iF<=300)
{
printf ("%3d %6.1f\n", iF, (5.0/9.0)*(iF-32));
iF+=20;
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 34
Do-While-Schleife
/*
Umrechnung Fahrenheit in Celsius nach:
°C = (5/9)(F-32)
*/
#include <stdio.h>
main()
{
unsigned int iF = 0;
In dieser Kombination
muss ein ';' am Ende der
Schleife stehen!
do
{
printf ("%3d %6.1f\n", iF, (5.0/9.0)*(iF-32));
iF+=20;
}
while (iF<=300);
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 35
Aufgaben (while-Schleife)
Tabelle von "unten" nach "oben" ausgeben
In der Ausgabe noch eine Index (1.) anfügen
Ausgabe einer Tabelle Celsius -> Fahrenheit
Unterschied bei der Definition signed, unsigned?
19.08.2010 | FP 5 | Kernphysik | M. Platz | 36
Continue Anweisung
Nur gültig in Schleifen
Durch diesen Aufruf wird der Programmablauf am Anfang der
Schleife fortgesetzt
for (i=0; i<10; i++)
{
if (irgendeine Komische Bedingung)
{
continue;
}
….
}
Ähnlich zur goto-Anweisung; wird bei klarer Programmierung nicht gebraucht !
19.08.2010 | FP 5 | Kernphysik | M. Platz | 37
Break-Anweisung
Beendet die übergeordnete Schleife
while (TRUE)
{
if (irgendeine Komische Bedingung)
{
break;
}
….
}
Oft durch ein sinnvolles Abbruchkriterium der Schleife vermeidbar;
Bei höheren Verschachtelungsstufen kann es undurchsichtig sein!
19.08.2010 | FP 5 | Kernphysik | M. Platz | 38
Aufgaben
Die ersten 100 Primzahlen berechnen lassen
Eine Primzahl ist eine natürliche Zahl mit genau zwei natürlichen
Zahlen als Teiler, nämlich der Zahl 1 und sich selbst
Optimieren
2k + 1
19.08.2010 | FP 5 | Kernphysik | M. Platz | 39
Switch - case
switch-case Anweisungen erlauben die Auswahl aus mehreren Alternativen
In switch() wird der zu testende Wert angegeben
case legt Marken fest, an denen die Programmausführung fortgesetzt wird,
wenn der in der Marke angegebene konstante Wert mit dem in der switch()Anweisung übereinstimmt
char c;
Wert von Interesse
c = getchar ();
switch (c)
Konstante
{
Auszuführender Code
case '\r':
case '\t':
Abruch der switch()-Anweisung
case ' ':
printf ("Whitespace\n");
break;
default:
printf ("Zeichen");
break;
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 40
Optionaler Ausdruck; Wenn
keine case-Anweisung
zutreffend ist, wird die
Ausführung hier fortgesetzt
Tag 3
Zeichen, Zeichenketten, Zeiger, Strukturen
Zeichen
Type für Zeichen: char
Die tatsächliche Bit-Breite eines Typs ist nicht im C-Standard
definiert, sondern systemabhängig
Definition des Wertebereiches in limits.h (/usr/include/limits.h)
In der Regel 8-Bit breit, Wertebereich -128 – 127
Gibt in der Regel den Code eines Zeichens im ASCII Standard
an
ASCII Standard enthält 128 Zeichen (33 Steuerzeichen, 95 druckbare
Zeichen)
Anmerkung: Auch die anderen Typen haben keine definierte Breite (oder Aufbau).
19.08.2010 | FP 5 | Kernphysik | M. Platz | 42
Aufgaben
ASCII Tabelle der Druckbaren Zeichen ausgeben (ab Zeichen
32)
Zeichen von 32 bis 255 ausgeben
Zeichensatz ändern und Programm erneut ausführen
ASCII Codes der Steuerzeichen aus der prinf()-Anweisung
ausgeben
19.08.2010 | FP 5 | Kernphysik | M. Platz | 43
Zeichenketten
Array aus Zeichen, letztes Zeichen '\0'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
char szString_1[16];
char szString_2[] = "Hello World";
char szString_3[] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
strcpy (szString_1, szString_2);
if (! strcmp (szString_1, szString_3))
{
printf ("Gleich\n");
}
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 44
Array
char szString[] = "Hello World";
Startadresse
… 'H' 'e'
'l'
'l'
0xAF00
Index
0
1
'o'
' ' 'W' 'o'
'r'
'l'
'd' '\0' …
0xAF0B
2
…
11
char c;
int iAddress;
c = szString[2]; // c enthält jetzt 'l'
iAddress = szString; /* iAddress enthält jetzt
die Adresse des Strings im
Arbeitsspeicher (0xAF00)*/
19.08.2010 | FP 5 | Kernphysik | M. Platz | 45
Aufgaben
Definition von strcpy() und strcmp() nachschlagen
Inhalt des uninitialisierten char-Arrays ausgeben
Inhalt des initialisierten char-Arrays ausgeben
String in ein zu kleines Array kopieren
Länge des Strings bestimmen
19.08.2010 | FP 5 | Kernphysik | M. Platz | 46
Pointer
Zeiger auf einen Speicherbereich (Adresse)
Inhaltsoperator
#include <stdio.h>
main()
{
char *pcTest;
Der Zeiger hat immer die für
das laufende System
benötigte Bit-Breite, um eine
Adresse zu speichern (32-Bit
System Î 32 Bit).
printf ("Adresse der Variablen: %4x\n", pcTest);
printf ("Inhalt der Variablen: %i\n", *pcTest); //Uninitialisiert
/*
Werte Zuweisung
*/
Für den Inhalt des Pointers
*pcTest = 'T';
}
Soll mehr als ein Zeichen gespeichert werden,
muss der entsprechende Speicher reserviert werden
19.08.2010 | FP 5 | Kernphysik | M. Platz | 47
wird die Bit-Breite reserviert,
die durch die Definition
gegeben ist (hier char).
Arbeiten mit Adressen
char szString_1[16];
char szString_2[] = "Hello World";
/* Definition von strcpy:
Startadresse
char* strcpy (char *str1, char *str2); */
strcpy (szString_1, szString_2);
… 'H' 'e'
'l'
'l'
'o'
' ' 'W' 'o'
'r'
'l'
0xAF00
Address-Operator
'd' '\0' …
0xAF0B
char szString_2[] = "Hello World";
char *pstrString_3;
char *pstrWorld;
pstrString_3 = szString_2;
pstrWorld = &szString_2[6];
19.08.2010 | FP 5 | Kernphysik | M. Platz | 48
Aufgaben
Arbeiten mit Pointern
Zuweisen von Adressen
Beispiel von vorheriger Folie in lauffähiges Programm umsetzen
Benutzung des Inhaltsoperator (*) zum Zugriff auf Speicherstellen
Mit Hilfe von Pointer den Inhalt des Arrays ausgeben
19.08.2010 | FP 5 | Kernphysik | M. Platz | 49
Strukturen
Zusammenfassung zusammengehörender Daten
Z.B. Punkt Î Zusammenfassung von x- und y-Koordinate
Beschreibung von Daten im Adressbereich
Registermap (z.B. eines Mikrocontrollers - Kurs 3)
struct point
{
int x;
int y;
}
Member
main()
{
struct point pt;
struct point *pPt;
pPt = &pt;
pt.x = 10;
pt.y = 20;
pPt->x = 10;
…
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 50
Auswahl des Members
Unions
Möglichkeit zur Speicherung unterschiedlicher Datentypen in
einem Speicherbereich
Der Compiler überwacht die Größe des Speicherbereichs.
Zugriff auf den falschen Datentyp sind implementierungsabhängig
Zugriff gleich zu Strukturen
union number
{
int iNum;
double dbNum;
char szNum[16];
}
main()
{
union number Number;
Number.iNum = 1;
/*
geht nicht:
Number.szNum = 1;
Geht:
strcpy (Number.szNum, "1");
*/
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 51
Typen
Neue (eigene) Typen werden definiert mit typedef
typedef unsigned char BYTE;
typedef struct point
{
int x;
int y;
}
POINT;
Void funktion (void)
{
BYTE by;
POINT pt;
…
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 52
Typ Definition
Typ Name
Funktionsaufrufe
Eine Funktion kann erst aufgerufen werden, wenn sie deklariert
wurde
Funktionsargumente (Inhalt der Variablen) werden vor dem
Aufruf kopiert
D.h. man kann einen Wert an die Funktion übergeben, bekommt die
Änderung aber nicht durch diese Variable zurück
Rückgabe von Werten ist nur durch die return-Anweisung möglich
Diese Einschränkung ist nur durch Pointer zu umgehen
Werden Pointer als Funktionsparameter benutzt, wird die
Adresse kopiert
Man greift dann direkt auf den Speicher zu (der Inhalt wird nicht
kopiert!)
Beim Rücksprung der Funktion bleiben die Änderungen im
Speicherbereich erhalten
19.08.2010 | FP 5 | Kernphysik | M. Platz | 53
Glossar
Definition
Festlegen des Typs einer Variablen und Reservierung von Speicher
Deklaration
Festlegen des Typs einer Variablen ohne Reservierung des Speichers
Initialisierung
Zuweisen des Wertes einer Variablen
Funktionsargument
Wert, der dem Funktionsaufruf übergeben wird
Funktionsparameter
Variable, die dem Funktionsaufruf übergeben wird
19.08.2010 | FP 5 | Kernphysik | M. Platz | 54
Aufgaben
Eingabe von Text mit Hilfe von getchar
Eingegebene Zeile in einem Puffer (Array) speichern
Einfache Verschlüsselung (Zeichen + Offset)
Eigene strcpy()-Funktion schreiben
char *strcpy (char *str1, char *str2);
Rückgabewert ist Zeiger auf das Ziel
Eigene strcmp()-Funktion schreiben
int strcmp (char* str1, char *str2);
Rückgabewert 0 wenn gleich, sonst kleiner oder größer 0
Typ "Komplexe Zahl" definieren (a+bi)
Funktionen zum Rechnen mit komplexen Zahlen schreiben
Addition: (a+bi) + (c+di) = (a+c) +(b+d)i
Multiplikation: (a+bi) * (c+di) = (ac – bd) + (ad+bc)i
19.08.2010 | FP 5 | Kernphysik | M. Platz | 55
Tag 4
Strukturiertes Programmieren
Strukturen
char char
int
short
Startadresse
typedef struct beispiel
{
char c1;
char c2;
int i;
short s1;
short s2;
}
19.08.2010 | FP 5 | Kernphysik | M. Platz | 57
short
Strukturiertes Programmieren
Allgemeine Regeln
Auf globale Variablen verzichten
Möglichst kurze und übersichtliche Funktionen
Sinnvolle Variablen-Namen
Schwer verständliche Konstrukte vermeiden, auch wenn man es für
genial hält
Bei größeren Projekten
Aufteilung des Programms auf mehrere C-Dateien
Zusammengehörender Code/Variablen in eine Datei
Möglichkeit eine eigene Bibliothek aufzubauen
Möglichst gleich dokumentieren
Kommentare vor den Funktionen, die Funktionalität, Parameter,
Rückgabewerte und Spezialitäten beschreiben.
19.08.2010 | FP 5 | Kernphysik | M. Platz | 58
Präprozessor
Vorstufe zum Compiler
Einfügen von Dateien (#include)
Definition von symbolischen Konstanten und Makros (#define)
Vordefinierte Makros (__LINE__, __FILE__, __DATE__, __TIME__)
Bedingungsabhängige Code-Generation (#if, #else, #ifdef, …)
Erweiterte Compiler-Steuerung (#warning, #error, #pragma)
19.08.2010 | FP 5 | Kernphysik | M. Platz | 59
Präprozessor
#include <stdio.h>
#include "mydef.h"
// Symbolische Konstante
#define MAX_VALUE
255
//Makro
#define ABS(A)
((A < 0) ? –A : A)
void test void (int iValue)
{
#ifdef DEBUG
printf ("Maximal zulässiger Wert: %i\n", MAX_VALUE);
#endif
if (iValue > MAX_VALUE)
{
printf ("Zu gross\n");
}
…
19.08.2010 | FP 5 | Kernphysik | M. Platz | 60
Speicherklassen
Variablen sind zunächst nur innerhalb des Blocks gültig, in dem
sie definiert wurden.
Definition ist die Festlegung des Typs und das Reservieren des
benötigten Speichers
Wird eine Variable in unterschiedlichen C-Dateien benötigt (ist
selten der Fall), darf sie nicht in allen Dateien definiert werden
Für jede Variable würde Speicher reserviert –> unterschiedliche
Variablen (aber gleicher Name)
Variable muss in allen Dateien deklariert werden (nur den Typ
festlegen) und in einer Datei definiert.
Deklaration einer Variablen für die Benutzung in
unterschiedlichen Dateien mit dem Keyword extern
extern gibt eine Speicherklasse an
19.08.2010 | FP 5 | Kernphysik | M. Platz | 61
Header-Dateien
Header-Dateien (Endung .h) sind Dateien, in denen i.d.R. keine
Code steht
Dienen zum
Deklarieren von Variablen und Funktionen
Definieren von Makros und Konstanten
Definieren eigener Typen, Unions
Werden also benutzt, um Informationen, die in
unterschiedlichen C-Dateien benötigt werden, zentral
zusammenzufassen
Header-Dateien sollten nur gemeinsam genutzte Information enthalten!
19.08.2010 | FP 5 | Kernphysik | M. Platz | 62
Beispiel
test.h
test.c
#ifndef test_h
#define test_h
#include "test.h"
#include "test.h"
/*
…
#include <stdio.h>
/*
Globale Variable, die
in allen Dateien, in
denen test.h
eingebunden wird,
definiert wird
*/
int iVariable;
/*
Hiermit wird nur der
Typ festgelegt, aber
kein Speicher
reserviert.
*/
extern int iGlobal;
#endif
19.08.2010 | FP 5 | Kernphysik | M. Platz | 63
test2.c
Hier wird iGlobal
definiert.
*/
int iGlobal;
…
void test (void)
{
iGlobal = 1;
iVariable = 0;
…;
}
void test2 (void)
{
if (iGlobal == 1)
{
…;
}
// undefiniert
if (iVariable ==
0)
{
;
}
…;
}
Speicherklassen II
Variablen innerhalb eines Blocks werden ungültig, wenn der
Block verlassen wird
In seltenen Fällen kann es nötig sein, dass eine Variable den
gespeicherten Wert behalten muss
Beim erneuten Eintritt in den Block ist die Variable mit dem zuvor
gespeicherten Wert wieder verfügbar
Dafür dient die Speicherklasse static
Globale statische Variablen sind nur innerhalb der C-Datei, in der sie
definiert wurden, gültig
19.08.2010 | FP 5 | Kernphysik | M. Platz | 64
Aufgaben
Benutzung der Speicherklasse static
Implementierung einer Funktion, die die Anzahl ihrer Aufrufe
protokolliert
19.08.2010 | FP 5 | Kernphysik | M. Platz | 65