Sie sind auf Seite 1von 34

Einfhrung in die Programmierung Vorlesung 6 W I S S E N 1

T E C H N I K

L E I D E N S C H A F T

Einfhrung in die Programmierung


DI Dr. Christian Safran, IICM DI Michael Steurer, IICM Univ.-Prof. DI Dr. techn. Frank Kappe, IICM

www.tugraz.at

Einfhrung in die Programmierung Vorlesung 6 2

Inhalt Teil 6:

Preprocessor Zeichenketten Dynamischer Speicher

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 3

Der Preprocessor

Erster Teil des C-Compilers Ersetzt Text durch anderen Text ("Makro Prozessor") Preprocessor Commands beginnen mit '#' Output des Pre-Prozessors ansehen mit: gcc E
! Das ist der Input fr den eigentlichen Compiler

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 4

#define
Parameterlose Makros:
#define identifier replacement

Beispiele:
#define #define #define #define MAX_LENGTH 30 PI 3.14159265 TWO_PI (2 * PI) FORMAT_STRING "%f\n"

char str[MAX_LENGTH + 1]; printf(FORMAT_STRING, TWO_PI);

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 5

#define
Makros mit Parametern Beispiele:

#define identifier(param1, ..., param_n) replacement

#define ABS(x) ((x) > 0 ? (x) : -(x)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define SWAP_INT(a, b) { int tmp = a; a = b; b = tmp; }

Achtung: Nicht mit Klammern sparen!


#define ABS1(x) x > 0 ? x : -x // bad ABS1(1 - 3) * 4 = 1 3 > 0 ? 1 - 3 : -1 - 3 * 4 = -13 statt +8 4 * ABS1(1 - 3) = 4 * 1 - 3 > 0 ? 1 - 3 : -1 3 = -2 statt +8

"! Klammern um jeden Parameter und um den ganzen Ausdruck !


DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 6

Unterschiede von Makros und Funktionen


Makros sind schneller
"! Kein Funktionsaufruf, Kopieren der Variablen, Rcksprung "! Dafr wird der Code evtl. etwas grer

Funktionen prfen Typ der Parameter


"! "! "! "! int max (int x, int y); float max(float x, float y); double max(double x, double y); ...

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 7

#include
Einfgen von Files an dieser Stelle im Source Code Typischerweise fr "Header"-Files
"! Deklarationen, Macros, Globale Variablen, Konstanten, ...

Standard-Headers:
"! z.B.: #include <stdio.h> "! werden im "Standard-Pfad" gesucht (z.B. /usr/include)

Eigene Headers:
"! z.B.: #include "my_types.h" "! z.B.: #include "../module_1/constants.h" "! werden ausgehend vom aktuellen Verzeichnis gesucht

Viele Headers lange Kompilierzeit


DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 8

Bedingte bersetzung
#if expression
"! wahr, wenn expression != 0 "! expression muss zur Compilezeit auswertbar sein (keine Variablen!)

#ifdef identifier
"! wahr, wenn identifier definiert wurde (mit #define)

#ifndef identifier
"! wahr, wenn identifier nicht definiert wurde (mit #define)

#else #endif
Im Unterschied zum "C-if" wird die Bedingung zur Compile-Zeit geprft (nicht zur Laufzeit), und entsprechend Code oder kein Code erzeugt!
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 9

Anwendungen
Generieren/Nichtgenerieren von Code in Abhngigkeit von:
"! "! "! "! "! Compiler-Version Betriebssystem Ziel-Hardware Software-Versionen (per gcc Didentifier=value) ...

Verhindern von mehrfachem #include Debug-Versionen Assertions


DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 10

Beispiel: debug.h

6_debug.h

file icon (cc) by Untergunter from http://www.iconarchive.com/show/leaf-mimes-icons-by-untergunter/text-x-c-icon.html

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 11

Anwendung: debug_test.c

6_debug_test.c

file icon (cc) by Untergunter from http://www.iconarchive.com/show/leaf-mimes-icons-by-untergunter/text-x-c-icon.html

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 12

Assert Macro
Im ANSI C Standard definiert assert(expression)

beendet Programm mit Fehlermeldung (Filename, Zeile, expression), wenn expression == 0

Ist ein Macro, dessen Code nur generiert wird, wenn NDEBUG nicht definiert ist
"! d.h. mit DNDEBUG wird "release" bzw. "ship" Version (ohne assert-Code) kompiliert, sonst die Debug-Version

Zum "automatischen" Finden von Programm-Fehlern


"! Funktionsparameter OK, NULL-Pointer, Array-Grenzen, ...
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 13

Beispiel

6_assert_demo.c

file icon (cc) by Untergunter from http://www.iconarchive.com/show/leaf-mimes-icons-by-untergunter/text-x-c-icon.html

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 14

Falsche Verwendung von assert:


Die "Release"-Version enhlt keinen Code von asserts Darf nur zum Testen von Zustnden verwendet werden, die im Echtbetrieb niemals auftreten sollten (d.h. Programmierfehlern) ! NICHT vorgesehen zum Testen von:
"! "! "! "! "! Gltigkeit von Benutzereingaben Out of Memory (malloc liefert NULL-Pointer) File existiert nicht Filesystem voll etc.

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 15

Speziallfall: Strings
Character arrays String-Konstanten: zwischen "-Zeichen Am Ende steht ein 0-Byte ('\0') Identisch:
char char char char hello[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; hello[6] = "hello"; hello[] = "hello"; *hello = "hello";

char buffer[100] = "hello"; // only 6 bytes used


DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 16

Fallen
Speicherplatz fr das 0-Byte nicht vergessen !
"! char str[5] = "hello"; // wrong!

"One-off Error" mal 2:


"! char *str = "hello" hat 5 Zeichen und braucht daher 6 Bytes (!!!) "! str[5] ist '\0' "! str[4] ist das letzte Zeichen 'o'

"Buffer Overflow":
"! Buffer ist zu klein fr den gerade bentigten String "! Spezielles Problem: Benutzer-Eingaben "! "Klassisches" Sicherheits-Problem
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 17

Noch mehr Fallen


char *str1 = "Das ist ein String"; char *str2 = "Ein String"; str1 = str2; Kopiert nur die Pointer, nicht den Inhalt! Der alte Wert von str1 geht verloren! if (str1 == str2) vergleicht nur die Pointer, nicht den Inhalt!
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 18

String-Funktionen (#include <string.h>)


strlen liefert Lnge eines Strings strcpy kopiert Inhalt eines Strings in einen anderen strcat hngt einen String am Ende eines anderen an strcmp vergleicht zwei Strings strchr sucht ein Zeichen in einem String strstr sucht einen String in einem String ... memset effizientes Initialisieren von Speicherbereichen memcpy effizientes Kopieren von Speicherbereichen memmove Kopieren von berlappenden Speicherbereichen siehe z.B. http://en.wikibooks.org/wiki/C_Programming/Strings
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 19

Beispiel: strcpy
1 char *strcpy(char *dest, char *src) 2 { 3 char *save = dest; 4 while (*dest++ = *src++); // fast but tricky! 5 return save; 6 }

Kopiert, bis *src == '\0' Liefert (Pointer auf) kopierten String Achtung: Kann nicht berprfen, ob dest gro genug ist! ( Aufpassen auf buffer overflow ) Sicherer: strncpy (siehe man strncpy)
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 20

Dynamische Speicherverwaltung
Oft wei man beim Schreiben des Programms noch nicht, wieviel Daten-Speicher man bentigen wird
"! abhngig von Benutzereingaben "! abhngig von Gre eines Files "! ...

C stellt dazu einen dynamischen Speicher ("Heap") zur Verfgung Der Programmierer ist fr die korrekte Verwaltung dieses Speichers verantwortlich (!!!!!!!)
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 21

Heap-Funktionen (1):
void *malloc(size_t bytes);
"! liefert Pointer auf einen Speicherblock der angegebenen Gre, oder NULL-Pointer (=0), wenn kein Speicher mehr da ist "! void* kann an jeden anderen Pointer-Typ zugewiesen werden "! Achtung: Gre in Bytes angeben ! "! Achtung: Inhalt des Speicherblocks ist undefiniert, d.h. nicht initialisiert ! "! Achtung: Den zurckgelieferten Pointer nie "verlieren" !

Beispiel:
int *my_block; if (my_block = malloc(100 * sizeof(int)) ... else printf("Out of memory\n");
DI Dr. Christian Safran, IICM

// 100 ints

Einfhrung in die Programmierung Vorlesung 6 22

Heap-Funktionen (2)
void free(void *base_ptr);
"! base_ptr ist der vorher durch malloc bzw. realloc gelieferte pointer "! Achtung: free nicht vergessen ( memory leak ) ! "! Achtung: free nicht zweimal auf denselben Speicherblock aufrufen ! "! Achtung: Nach free nicht mehr auf den Speicher zugreifen !

Beispiel:
char *line = malloc(80); ... free(line); line = NULL; // line with 80 characters // cannot be accessed/freed

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 23

Heap-Funktionen (3)
void *realloc(void *base_ptr, size_t bytes);
"! vergrert oder verkleinert den Speicherblock bei base_ptr auf die angegebene neue Gre in Bytes, liefert neuen Pointer zurck "! Beim Vergrern: Der alte Inhalt bleibt erhalten (wird evtl. kopiert), der Rest ist uninitialisiert (!) "! Beim Vergrern: Wenn kein Speicher mehr da ist NULL-Pointer "! Beim Verkleinern: Rest wird freigegeben (wie bei free) "! Achtung: keine portable Mglichkeit, Gre nachtrglich zu erfahren !

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 24

Z.B.: Datenstruktur fr Text-Editor


Identisch:
char *lines[]; char **lines;
lines 0x...... 0x...... 0x...... 0x...... 0x...... NULL T e x t \0 lines[2][4] e k i u n r \0 z e r \0 D a s i s t \0

// array of pointers to strings // same thing

lines[2]

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 25

Operationen auf dieser Datenstruktur


void initialize(); erzeugt "leere" Datenstruktur void freeAll(); gibt den ganzen verwendete Speicher wieder frei int countLines(); zhlt die Zeilen (hnlich wie strlen die Zeichen zhlt) void insertLine(int line, char *str); fgt eine Zeile ein void removeLine(int line); lscht eine Zeile void insertString(int line, int col, char *str); fgt einen String in einer Zeile und Spalte ein usw.; siehe editor_demo.c auf der Website
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 26

Beispiel: insertLine()
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 // ----------------------------------------------------------// insert a line before the line specified void insertLine(int line, char *str) { int num_lines = countLines(); // increase lines size by one line pointer: lines = realloc(lines, (num_lines + 2) * sizeof(char*)); // move line pointers backwards: memmove(&lines[line + 1], &lines[line], (num_lines - line+1) * sizeof(char*)); // insert the new line: lines[line] = malloc(strlen(str) + 1); strcpy(lines[line], str); }

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 27

Beispiel: removeLine()
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 // --------------------------------------------------------// remove the specified line void removeLine(int line) { int num_lines = countLines(); // free the memory used by this line: free(lines[line]); // move line pointers forward: memmove(&lines[line], &lines[line + 1], (num_lines line + 1) * sizeof(char*)); // decrease lines size by one line pointer: lines = realloc(lines, num_lines * sizeof(char*)); }

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 28

Ganz hnlich: Command-Line Arguments

6_cl_args.c

file icon (cc) by Untergunter from http://www.iconarchive.com/show/leaf-mimes-icons-by-untergunter/text-x-c-icon.html

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 29

Die Funktion getchar()


#include <stdio.h> int getchar();

Liefert das nchste Zeichen vom "standard input" Wenn es kein nchstes Zeichen gibt: liefert EOF (= -1) Achtung: Return-Type ist int, nicht char Gegenteil: int putchar(int c); Beispiel (kopiert input auf output):
int character; while ((character = getchar()) != EOF) putchar(character);
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 30

Beispiel: read line

6_read_line.c

file icon (cc) by Untergunter from http://www.iconarchive.com/show/leaf-mimes-icons-by-untergunter/text-x-c-icon.html

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 31

Hinweis zu read_line.c
Das Beispiel dient nur dem Verstndnis. "! Byteweises Einlesen Fr die bungen "! Blockweises Einlesen "! Definierte Blockgre

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 32

5. Hausbung
Strings & dynamischer Speicher "! Lies Text von Console bis EOF "! Speichere in dynamischem Speicher
"! ggf vergrern

"! Gib den Text rckwrts wieder aus "! Testen mit
"! ./hw5 < input.txt
DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 33

5. Hausbung
Beispiel

Hallo Welt!\n! Jetzt noch ein Zeilenumbruch und dann EOF.\n[EOF]! \n! .FOE nnad dnu hcurbmunelieZ nie hcon tzteJ\n! !tleW ollaH\n!

DI Dr. Christian Safran, IICM

Einfhrung in die Programmierung Vorlesung 6 34

5. Hausbung
Aufgabenstellung im Wiki
"! Halten Sie sich genau an die Anforderungen! "! Ihre Abgabe wird automatisiert getestet. "! Feedback: Anzahl der bestandenen Testflle.

Fragen von allgemeinem Interesse


"! Newsgroup tu-graz.lv.ep "! Zuerst lesen, dann posten

DI Dr. Christian Safran, IICM