edv1 - 04präprozessor der c-präprozessor. edv1 - 04präprozessor 2 der c-präprozessor bevor ein...
Post on 05-Apr-2015
111 Views
Preview:
TRANSCRIPT
EDV1 - 04Präprozessor
Der C-Präprozessor
ED
V1 - 04P
räpro
zessor
2
Der C-Präprozessor
• Bevor ein Programm vom eigentlichen C-Compiler bearbeitet wird, wird es vom C-Präprozessor bearbeitet. Dabei werden reine Textersetzungen durchgeführt. Der Präprozessor erzeugt den vom Compiler zu übersetzenden Quelltext.
C-Quelltext mitPräprozessor-anweisungen
C-Quelltext ohnePräprozessor-anweisungen
Objektmodule
AusführbaresProgramm Bibliotheken
Prä
proz
esso
r
Com
pile
rV
erbi
nder
ED
V1 - 04P
räpro
zessor
3
Die Präprozessoranweisungen
• Anweisungen für den Präprozessor beginnen immer mit # in der ersten Spalte.
• Es gibt folgende Präprozessoranweisungen:– #include : Einfügen einer Datei– #define : Definieren einer Konstanten oder eines Makros– #if (#ifdef, #ifndef) - #elif - #else – #endif :
bedingte Übersetzung
ED
V1 - 04P
räpro
zessor
4
Die include-Anweisung
• Die include-Anweisung fügt eine Datei in den Quelltext ein.• Es ist genau so als ob der Inhalt der eingefügten Datei statt der
include-Anweisung steht.
Datei „limits.h“ enthält:
char min_char=-128;
char max_char=127;
Datei „prog.c“ enthält:
#include "limits.h"
int main()
{
char c;
for (c=min_char;c<max_char;c++)
printf("char[%i]=%c\n",c,c);
printf("char[%i]=%c\n",c,c);
}
ED
V1 - 04P
räpro
zessor
5
• Compileraufruf:gcc –ansi prog.c –E –o prog.ierzeugt die Datei „prog.i“
# 1 "prog.c"# 1 "limits.h" 1char min_char=-128;char max_char=127;# 1 "prog.c" 2int main(){char c;for (c=min_char;c<max_char;c++)printf("char[%i]=%c\n",c,c);printf("char[%i]=%c\n",c,c);}
ED
V1 - 04P
räpro
zessor
6
• Zwei Formen der include-Anweisung– #include <filename>
sucht die Datei im Standarbibliothekspfad– #include "filename"
sucht die Datei im aktuellen Verzeichnis• Z.B.:
#include <stdio.h>
#include "limits.h"• Anwendungen der include-Anweisung:
– Einfügen von „header“-Dateien, die die Schnittstellendefinition von Prozeduren enthalten
– Einfügen von Definitionen von Konstanten und Typen
ED
V1 - 04P
räpro
zessor
7
Die define - Anweisung
• Mit der define-Anweisung werden Konstanten und Macros definiert. Allgemeine Form:#define <NAME> <ZEICHENKETTE>
• Nach dieser define-Anweisung wird jedes Auftreten von <NAME> als ganzes Wort im Text durch <ZEICHENKETTE> ersetzt.
ED
V1 - 04P
räpro
zessor
8
Beispiel
• limits.h#define MIN_CHAR –128#define MAX_CHAR 127
• prog.c#include "limits.h"int main(){char c;for (c=MIN_CHAR;c<MAX_CHAR;c++)printf("char[%i]=%c\n",c,c);printf("char[%i]=%c\n",c,c);}
ED
V1 - 04P
räpro
zessor
9
# 1 "prog.c"
# 1 "limits.h" 1
# 1 "prog.c" 2
int main()
{
char c;
for (c= -128 ;c< 127 ;c++)
printf("char[%i]=%c\n",c,c);
printf("char[%i]=%c\n",c,c);
}
ED
V1 - 04P
räpro
zessor
10
• Zusammen mit der include-Anweisung kann damit ein Programm sehr flexible geschrieben und dann durch geringe Änderungen an die Hardware angepasst werden.
• Beispiel:#define TEXT1 "Das ist ein ganz langer Text."#define TEXT2 "Das ist noch ein langer Text."#define TEXT3 "Das ist der dritte lange Text."printf(" %s\n %s\n %s\n",TEXT1,TEXT2,TEXT3);
• define-Anweisung wird genutzt, um Programme übersichtlicher zu gestalten und bestimmte möglicherweise öfter zu ändernde Programmteile an einer Stelle zu konzentrieren.
• define-Anweisungen können ersetzt werden durch die Angabe des D-Schalters beim Compilerauffruf. Z.B:gcc –DTRUE=1 hello.cbewirkt die Einfügung der Anweisung#define TRUE 1vor das Programm hello.c.
ED
V1 - 04P
räpro
zessor
11
Macros
• Macros dienen der parametrisierten Ersetzung von Zeichenketten durch Ausdrücke.
• Beispiel:#define MAX(A,B) (((A)>(B))?(A):(B))float a,b,c;c=MAX(a+b,a-b);wirkt wiec=(((a+b)>(a-b))?(a+b):(a-b));
• Achtung!– Immer ausreichend Klammern gebrauchen!– Trennzeichen in der define-Anweisung trennen den zu
definierenden Namen von der Definition, solange sie nicht in Klammern eingeschlossen sind. #define MAX(A,B) (((A)>(B))?(A):(B))#define MAX( A,B) (((A)>(B))?(A):(B))#define MAX (A,B) (((A)>(B))?(A):(B))sind zulässig haben aber z.T. unterschiedliche Bedeutung
ED
V1 - 04P
räpro
zessor
12
Beispiel
#define MAX(A,B) (((A)>(B))?(A):(B))
#define MIN(A,B) (((A)<(B))?(A):(B))
int main()
{
int i,j;
int max=MAX(i,j);
int min=MIN(i,j);
int m=MAX(i-j,j-i)*MIN(i-j,j-i);
}
ED
V1 - 04P
räpro
zessor
13
# 1 "prog.c"
int main()
{
int i,j;
int max= ((( i )>( j ))?( i ):( j )) ;
int min= ((( i )<( j ))?( i ):( j )) ;
int m= ((( i-j )>( j-i ))?( i-j ):( j-i )) * ((( i-j )<( j-i ))?( i-j ):( j-i )) ;
}
ED
V1 - 04P
räpro
zessor
14
Spezielle Operatoren in Macros• #<NAME> bewirkt, dass der Wert nach dem Ersetzen in "-" gesetzt
wird. • <NAME1>##<NAME2> bewirkt die direkte Verkettung der Werte von
<NAME1> und <NAME2>.
ED
V1 - 04P
räpro
zessor
15
Beispiel
#define PRINT(X) printf("Wert von %s = %i\n",#X,X)
#define INIT(A,B) A##B=(A)*100+(B)
int main()
{
int c=20;
int j=0;
int INIT(c,j);
PRINT(c);
PRINT(j);
PRINT(cj);
}
ED
V1 - 04P
räpro
zessor
16
# 1 "oper.c"
int main()
{
int c=20;
int j=0;
int cj =( c )*100+( j ) ;
printf("Wert von %s = %i\n","c", c ) ;
printf("Wert von %s = %i\n","j", j ) ;
printf("Wert von %s = %i\n","cj", cj ) ;
}
ED
V1 - 04P
räpro
zessor
17
Vordefinierte Macros - GNUC__LINE__
__FILE__
__DATE__
__TIME__
Weitere von Compilern abhängige Macros:
__STRICT_ANSI__ 1
_LANGUAGE_C 1
__GNUC__ 2
__GNUC_MINOR__ 7
__unix__ 1
ED
V1 - 04P
räpro
zessor
18
Beispielint main ()
{
printf("Filename : %s\n",__FILE__);
printf("Date : %s\n",__DATE__);
printf("Time : %s\n",__TIME__);
printf("LineNr. : %i\n",__LINE__);
}
# 1 "vordef.c"
int main ()
{
printf("Filename : %s\n","vordef.c");
printf("Date : %s\n","May 1 2000");
printf("Time : %s\n","09:51:49");
printf("LineNr. : %i\n",6);
}
ED
V1 - 04P
räpro
zessor
19
Macros als Compiler-Schalter
• Durch Angabe des Compilerschalters "-D" können Macros nachträglich definiert werden. Z.B.:cc hello.c –Dname1 –Dname2=wertentspricht der Einfügung von#define name1#define name2 wertam Anfang des Quelltextes hello.c
• Wird häufig benutzt um spezielle Versionen aus einer Quelle zu erzeugen, z.B.:– Hardwareabhängigkeit– Genauigkeitsversionen (float, double)– Größenversionen– Unterschiedliche Interface (X11, Windows)
ED
V1 - 04P
räpro
zessor
20
Bedingte Übersetzung• #if (#ifdef, #ifndef) - #elif - #else – #endif• Mit Hilfe der Anweisungen zur bedingten Übersetzung können
bestimmte Teile des C-Programmes zur Übersetzung ausgewählt bzw. von der Übersetzung ausgenommen werden.
• Allgemeine Form:#if AUSDRUCK1text1#elif AUSDRUCK2text2#elif AUSDRUCK3text3#elsetext4#endif
• Es sind nur einfache logische Ausdrücke mit numerischen Werten erlaubt. FALSE==0, TRUE != 0.
ED
V1 - 04P
räpro
zessor
21
• Statt #if AUSDRUCK kann auch #ifdef MACRO bzw. #ifndef MACRO stehen. In diesen wird geprüft ob das Macro definiert bzw. nicht definiert ist.
ED
V1 - 04P
räpro
zessor
22
Beispiel
int main ()
{
#if BETA && DEMO
printf(
"Beta-Version %i\n%i - Tage Demo\n",BETA,DEMO);
#elif BETA
printf(
"Beta-Version %i\nunbegrenzte Lizenz\n",BETA);
#elif DEMO
printf("Final Release\n%i - Tage Demo\n",DEMO);
#else
printf("Final Release\nunbegrenzte Lizenz\n");
#endif
}
ED
V1 - 04P
räpro
zessor
23
• gcc –ansi bed.c –DBETA=2 –DDEMO=30 –E –o bed.iint main (){
printf("Beta-Version %i\n%i - Tage Demo\n",2 ,30 );}
• gcc –ansi bed.c –DBETA=0 –DDEMO=30 –E –o bed.iint main (){
printf("Final Release\n%i - Tage Demo\n",30 );}
• gcc –ansi bed.c –DBETA=2 –DDEMO=0 –E –o bed.iint main (){
printf("Beta-Version %i\nunbegrenzte Lizenz\n",2 );}
• gcc –ansi bed.c –DBETA=0 –DDEMO=0 –E –o bed.iint main (){
printf("Final Release\nunbegrenzte Lizenz\n");}
ED
V1 - 04P
räpro
zessor
24
Typisches Header-File
stdio.h
#ifndef _INC_STDIO
#define _INC_STDIO
...
#endif /* _INC_STDIO */
top related