home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
tcpp
/
helpme!.doc
next >
Wrap
Text File
|
1990-06-09
|
33KB
|
730 lines
TURBO C++: ANTWORTEN AUF ALLGEMEINE FRAGEN
I n s t a l l a t i o n u n d S t a r t
----------------------------------------------------------------------
F. Wie wird Turbo C++ auf meinem System installiert?
A. Legen Sie die Diskette 1 ("INSTALL") in das Laufwerk A:
Ihres Computers, setzen Sie dieses Laufwerk mit dem Befehl
A: <RETURN>
auf der DOS-Kommandoebene als Standard, und geben Sie dann den
Befehl
INSTALL <RETURN>
ein. INSTALL fragt nun als erstes, von welchem Disketten-
laufwerk die Dateien gelesen werden sollen. Tippen Sie
A: <RETURN>
Als nächstes erscheint nun das Menüsystem von INSTALL. Folgen Sie
den Anweisungen.
F. Wie wird Turbo C++ nach der Installation gestartet?
A. Geben Sie auf der DOS-Kommandoebene
TC <RETURN>
ein, nachdem Sie Turbo C++ installiert haben.
Das Handbuch Einführung (Kapitel 2 des Benutzerhandbuchs) zeigt
schrittweise, wie es von diesem Punkt an weitergeht.
F. Wo liegen die Unterschiede zwischen TC.EXE und TCC.EXE?
A. Das Turbo C++ Programmierpaket enthält zwei voneinander unabhängige
Compiler: die integrierte Entwicklungsumgebung (TC.EXE) und die
Kommandozeilen-Version TCC.EXE.
Bei ersterer handelt es sich um einen "Programmverbund" aus
Compiler, Editor, Debugger, kontextbezogener Hilfestellung usw., wobei
die einzelnen Funktionen über ein Menüsystem miteinander verbunden sind;
bei zweiterem um einen reinen Compiler, der durch die Eingabe
einer Kommandozeile (von der DOS-Kommandoebene aus) gestartet wird
und während der Bearbeitung eines C-Quelltextes keine weitere
Interaktion mit dem Benutzer ausführt.
F. Was ist eine "Konfigurationsdatei"?
A. Über eine Konfigurationsdatei wird Turbo C++ mitgeteilt, welche
Einstellungen (Compiler-Schalter, Optionen usw.) als Standard ver-
wendet werden sollen und in welchen Directories sich Include-
Dateien bzw. Bibliotheken befinden.
TC.EXE - die integrierte Entwicklungsumgebung - sucht beim
Start nach einer Datei namens TCCONFIG.TC; TCC.EXE - die
Kommandozeilen-Version des Compilers - nach einer Datei namens
TURBOC.CFG.
F. Wie werden Konfigurationsdateien erzeugt?
A. Von der integrierten Entwicklungsumgebung aus: durch die
Auswahl von Options/Save options. Turbo C++ speichert hier
sämtliche Daten, die von den durch Borland gesetzten
Vorgaben abweichen, in einer Datei, die standardmäßig
den Namen TCCONFIG.TC trägt.
Für die Kommandozeilen-Version: entweder durch
Konvertierung der Datei TCCONFIG.TC mit dem Programm
TCCONFIG.EXE (siehe Referenzhandbuch) oder durch die direkte
Eingabe mit einem ASCII-Editor (siehe Referenzhandbuch, Anhang).
I n t e g r i e r t e E n t w i c k l u n g s u m g e b u n g
----------------------------------------------------------------------
F. Anscheinend findet Turbo C++ meine mit #include <...> angegebenen
Dateien nicht. Wieso?
A. Der Compiler sucht Include-Dateien in den Directories, die über
Options/Directories/Include directories angegeben sind. Das Pro-
gramm INSTALL trägt hier das Directory ein, in das auch die
*.H-Dateien von den Originaldisketten kopiert wurden.
Wenn Sie eigene Include-Dateien erstellen und diese Dateien
in einem anderen Directory speichern, müssen Sie den Eintrag
in O/D/Include directories entsprechend erweitern. Mehrere
Einträge trennen Sie durch einen Strichpunkt ";".
F. Ich erhalte die Meldung 'Linker error: Unable to open
input file 'C0x.OBJ''. Wieso?
A. Der Linker sucht den Startcode und die Laufzeitbibliotheken in den
Directories, die über Options/Directories/Library directories an-
gegeben sind. Das Programm INSTALL trägt hier das Directory ein,
in das auch die *.LIB und *.OBJ-Dateien von den Originaldisketten
kopiert wurden.
F. Wie kriege ich den Compiler dazu, meine eigenen Bibliotheken anstelle
der Standardbibliotheken einzubinden? Wie sieht es mit mehreren
Quelltexten für ein Programm aus?
A. Siehe Benutzerhandbuch, Kapitel 3.
F. Der Linker beharrt darauf, Funktionen wie initgraph() nicht zu
kennen. Wieso?
A. Setzen Sie den Schalter Options/Linker/Graphics Library auf ON oder
definieren Sie eine .PRJ-Datei, die graphics.lib explizit aufführt.
F. Bei der Compilierung eines ganz gewöhnlichen Programms reagiert der
Compiler auf die Zeile #include <stdio.h> mit der Meldung
"Unable to open include file 'stdarg.h'".
A. Aller Wahrscheinlichkeit nach wurde die Maximalzahl von Dateien
überschritten, die DOS gleichzeitig offen halten kann. Fügen
Sie Ihrer Datei CONFIG.SYS die Zeile
FILES=20
hinzu - danach reserviert DOS genügend Platz, um bis zu 20
Dateien gleichzeitig bearbeiten zu können.
ACHTUNG: Die Datei CONFIG.SYS wird nur beim Start des Systems
ausgewertet - Sie müssen den Computer also neu starten, damit
Ihre Änderungen wirksam werden.
F. Die Farben der Menüs von Turbo C++ passen absolut nicht zu meinem
Schreibtisch. Was tun?
A. Benutzen Sie TCINST.EXE zur Verwirklichung Ihrer eigenen Vorstellungen.
F. Wie kann ich einen Quelltext am einfachsten drucken?
A. Aktivieren Sie den Editor von Turbo C++, laden Sie den Quelltext, und
geben Sie den Tastenbefehl Ctrl-K-P ein. Dieser Befehl sendet entweder
den momentan (mit Ctrl-K-B und Ctrl-K-K markierten) Block zum Drucker
- oder, falls überhaupt kein Block markiert ist, die gesamte Datei.
F. Beim Aufruf von MAKE, Run oder bei der Aktivierung des Debuggers
übersetzt der Compiler manchmal verschiedene Teile meines Programms
von neuem - obwohl die einzelnen Module wirklich bereits auf dem
letzten Stand der Dinge sind.
A. MAKE orientiert sich ausschließlich an Datum und Uhrzeit
der einzelnen Dateien. Wenn Sie beispielsweise mit setfattr() expe-
rimentiert und einem Ihrer Quelltexte ein "Zukunftsdatum" verpaßt
haben, dann wird die entsprechende .OBJ-Datei für MAKE bis zum
tatsächlichen Erreichen dieses Zeitpunkts immer "älter" sein.
Diese und ähnliche Probleme lassen sich mit TOUCH lösen - einem
Programm, das sämtlichen angegebenen Dateien die momentane System-
zeit gibt.
F. Warum funktionieren meine alten Turbo C++ Projekt-Dateien nicht mehr?
A. Projekt-Dateien enthalten nun wesentlich mehr Informationen und werden
deswegen nicht mehr im ASCII-Format gespeichert. Wenn Sie eine Projekt-
Datei erzeugen möchten, wählen Sie die Option Project aus dem Hauptmenü
und folgen den Menüs. Alte Projekt-Dateien können mit dem Hilfsprogramm
PRJCNVT.EXE (in UTIL.DOC beschrieben) in das neue Format konvertiert
werden.
F. Warum wird meine Projekt-Datei automatisch geladen, wenn ich TC starte?
Ich möchte eigentlich mit anderen Dateien arbeiten.
A. Wenn sich nur eine Projekt-Datei im aktuellen Directory befindet,
lädt Turbo C++ diese Datei bei jedem Start. Wenn sich keine oder mehrere
Projekt-Dateien in diesem Directory befinden, wird keine automatisch
geladen.
F. Die rechte Maustaste ist nicht aktiv. Kann ich das ändern?
A. Unter der Option Options/Environment/Mouse finden Sie ein Dialog-Fenster
für die rechte Maustaste. Sie können sie damit beliebig umdefinieren.
F. Wie bringe ich Turbo C++ dazu, Expanded oder Extended Memory zu benutzen?
A. Benutzen Sie den Schalter /X für Extended und /E für Expanded Memory,
wenn Sie Turbo C++ starten.
F. Beim Compilieren bekomme ich den Fehler "Error: C:\TC\INCLUDE\STDIO.H:
Overlays only supported in medium, large, and huge models
Was ist los?
A. Sie haben die Option Overlay Support ausgewählt, die nicht in den kleinen
Speichermodellen tiny, small und medium funktioniert. Deaktivieren Sie
die Option mit Options/Compiler/Code generation/Overlay Support
F. Wenn ich nach dem Editieren einer Datei eine andere Datei laden will,
bleibt die erste Datei auf dem Bildschirm. Wie kann ich sie entfernen?
A. Schließen Sie mit Alt-F3 die aktuelle Datei. Mit F6 wechseln Sie
zwischen Dateien.
F. Beim Suchen/Ersetzen muß ich jede Änderung bestätigen, auch wenn ich
Change All ausgewählt habe.
A. Deaktivieren Sie die Option "Prompt on replace" auf der linken Seite des
Dialog-Fensters.
F. Wenn ich Pseudo-Register wie _AX verwende, erhalte ich beim Compilieren
Meldungen wie "Undefined symbol '_AX' in function...". Warum?
A. Pseudo-Register können nur im Turbo C++ und ANSI-Modus des Compilers
verwendet werden. Die Option finden Sie unter Options/Compiler/
Source menu.
F. Wie kann ich, ohne eine Maus zu verwenden, Code zwischen Dateien
kopieren?
A. Markieren Sie den Block mit Ctrl-K-B (Anfangsmarke) und Ctrl-K-K
(Endemarke), und benutzen Sie dann die Copy- und Paste-Befehle des
Edit-Menüs. Sie können einen Block ebenso mit SHIFT-Pfeiltaste
markieren.
K o m m a n d o z e i l e n - V e r s i o n
----------------------------------------------------------------------
F. Anscheinend findet Turbo C++ meine mit #include <...> angegebenen
Dateien nicht. Wieso?
A. Der Compiler sucht Include-Dateien in den Directories, die über
den Parameter -I angegeben sind. Das Programm INSTALL erzeugt eine
Konfigurationsdatei (TURBOC.CFG), die von TCC.EXE automatisch gelesen
wird und in der das Directory eingetragen ist, in das auch die
*.H-Dateien von den Originaldisketten kopiert wurden.
F. Ich erhalte die Meldung "Linker error: Unable to open
input file 'C0x.OBJ'". Wieso?
A. Der Linker sucht den Startcode und die Laufzeitbibliotheken in den
Directories, die über den Parameter -L der Konfigurationsdatei
TURBOC.CFG angegeben sind. Das Programm INSTALL trägt hier das
Directory ein, in das auch die *.LIB und *.OBJ-Dateien von den
Originaldisketten kopiert wurden.
Hinweis: Bei einem direkten Aufruf von TLINK müssen Sie den Such-
weg für Bibliotheken und Startcode explizit angeben - TLINK liest
die Konfigurationsdatei TURBOC.CFG nicht.
F. Der Linker beharrt darauf, Funktionen wie initgraph() nicht zu
kennen. Wieso?
A. TCC sucht die Grafik-Bibliothek (graphics.lib) nur nach expliziter
Anweisung ab. Zur Compilierung von BGIDEMO ist beispielsweise die
folgende Kommandozeile notwendig:
TCC BGIDEMO.C GRAPHICS.LIB <RETURN>
Hinweis: Hier wurde vorausgesetzt, daß eine Konfigurationsdatei
TURBOC.CFG mit den Suchwegen für Bibliotheksdateien existiert.
E i n - u n d A u s g a b e
----------------------------------------------------------------------
F. Die Befehle cprintf("Hello\n"); cprintf("world\n"); ergeben
Hello
world
Woran liegt das?
A. cprintf() arbeitet in dieser Version von Turbo C++ so, wie
es eigentlich von Anfang an vorgesehen war - '\n' wird nicht
(wie bei printf) in eine CR/LF-Kombination "übersetzt", sondern
tatsächlich als einzelnes LF-Zeichen ausgegeben.
Wenn Sie den Cursor nicht nur eine Zeile tiefer, sondern auch
noch wieder in die Spalte 1 dieser Zeile setzen wollen, müssen Sie
das CR-Zeichen beim Aufruf von cprintf() direkt angeben: Die Befehls-
folge cprintf("Hello\n\r"); cprintf("world\n\r"); erzeugt das gewünschte
Ergebnis (wobei es keine Rolle spielt, ob '\r' vor '\n' oder danach
angegeben wird).
F. Wie kann ich mit einem Programm Ausgaben auf dem Drucker erzeugen?
A. Ab der Version 1.5 von Turbo C ist eine FILE-Variable namens stdprn
in der Datei stdio.h definiert, die beim Start des Programms auto-
matisch geöffnet wird. Ein Beispiel dazu:
#include <stdio.h>
main()
{
fprintf(stdprn, "Hello, world\n");
}
Die meisten Drucker arbeiten übrigens mit einer zeilenweisen Pufferung -
tatsächlich gedruckt wird also erst nach dem abschließenden '\n'.
F. Bei der Bearbeitung einer Binärdatei scheint sich Merkwürdiges zu tun,
wenn die Werte 0x0D und 0x0A gelesen oder geschrieben werden. Was tun?
A. Wahrscheinlich haben Sie die Datei ohne den Zusatz "b" geöffnet -
die Routinen zur Dateibearbeitung gehen dann von einer Textdatei aus
und übersetzen die Bytefolge 0x0D 0x0A als "CR/LF" in ein einzelnes LF beim
Lesen bzw. erweitern den Wert 0x0A als "LF" auf eine CR/LF-Folge beim
Schreiben.
Öffnen Sie die Datei explizit im Binärmodus, wie es das folgende
Beispiel zeigt:
#include <stdio.h>
main()
{
FILE *binary_fp;
char buffer[100];
binary_fp = fopen("MYFILE.BIN", "rb");
fread(buffer, sizeof(char), 100, binary_fp);
:
}
F. Wieso weigern sich printf() und puts(), farbige Zeichen zu erzeugen?
A. Weil diese beiden Funktionen mit Standardattributen arbeiten. Für
bunte Ausgaben und andere Spezialitäten des IBM PC sind die Routinen
cprintf() und cputs() vorgesehen:
#include <conio.h>
main()
{
textcolor(BLUE);
cprintf("Ich bin blau.");
}
F. Wie wird ein long-Wert mit printf ausgegeben?
A. Mit "%ld":
long int l = 70000L;
printf("%ld", l);
F. Wie wird ein Wert im Format long double (= Extended) ausgegeben?
A. Mit "%Lf":
long double ldbl = 1E500;
printf("%Lf", ldbl);
B e i s p i e l p r o g r a m m e
----------------------------------------------------------------------
F. Wie wird BGIDEMO compiliert und gestartet?
A. 1. Die folgenden Dateien müssen sich im momentan gesetzten Directory
befinden:
BGIDEMO.C
*.BGI <- die Grafiktreiber
*.CHR <- die Zeichensätze
2. Starten Sie TC mit dem Befehl
TC bgidemo <RETURN>
3. Geben Sie den Tastenbefehl Ctrl-F9.
F. Wie läßt sich mit Turbo C++ eine .COM-Datei erzeugen?
A. Zusammen mit den DOS-Versionen bis (inklusive) 3.2 wird ein Programm
namens EXE2BIN ("EXE to Binary") ausgeliefert, über das sich
.EXE-Programme des Speichermodells TINY ins .COM-Format umwandeln
lassen.
Wenn Sie EXE2BIN nicht Ihr eigen nennen: der zur Kommandozeilen-
Version von Turbo C++ gehörige Linker läßt sich bei der Compilierung
von TINY-Programmen mit dem Parameter /t aufrufen und spart
den Umweg über eine .EXE-Datei. Der Aufruf von TCC mit
tcc -mt -lt hello
compiliert HELLO.C und erzeugt dann die Datei HELLO.COM. (Das "-l" im
Parameter "-lt" steht für "direkte Weitergabe des folgenden Befehls" -
also "t" - an den Linker, vgl. Referenzhandbuch, Anhang).
Hinweis: Die mathematische Bibliothek von Turbo C++ arbeitet wegen des
Emulators in jedem Modell mit mehreren Segmenten. TINY-Programme, die
Fließkommazahlen und -routinen benutzen, lassen sich deshalb auch mit
TLINK nicht im .COM-Format speichern.
G r a f i k
----------------------------------------------------------------------
F. Mein Programm endet bei der ersten Grafikfunktion mit der Meldung
BGI Error: graphics not initialized (use 'initgraph')
- und das, obwohl initgraph() definitiv vorher aufgerufen wurde.
A. initgraph() hat seine Funktion aus irgendeinem Grund (höchstwahr-
scheinlich: Grafiktreiber nicht im momentan gesetzten Directory)
nicht erfüllen können. Fügen Sie nach dem Aufruf von initgraph() eine
Prüfung des Ergebnisses von graphresult() ein, und ermitteln Sie auf
diese Weise den Fehlerstatus des Grafikpakets:
#include <graphics.h>
main()
{
int gerr; /* für das Ergebnis von graphresult() */
int gdriver = DETECT, gmode;
/* Initialisierung des Grafikpakets über die automatische
Prüfung der Hardware. .BGI- und .CHR-Dateien werden im
Directory C:\TURBOC gesucht:
*/
initgraph(&gdriver, &gmode, "C:\\TURBOC"); /* "\\" ! */
if ((gerr = graphresult()) != grOk)
{
printf("Fehler : %s\n", grapherrormsg(gerr));
exit(1);
}
/* ..... */
}
M a t h e m a t i s c h e s
----------------------------------------------------------------------
F. Die mathematischen Bibliotheksfunktionen liefern völlig unsinnige
Ergebnisse.
A. Vor der Verwendung von Funktionen wie cos() und tan() müssen
Sie math.h mit #include in ihr Programm aufnehmen - ansonsten
nimmt der Compiler an, daß diese Routinen den (Standard-)Ergebnistyp
int haben und codiert entsprechende Zuweisungen. Da die meisten
mathematischen Routinen Werte vom Typ double liefern, sind die
Ergebnisse tatsächlich recht wunderlich. Beispiel:
/* FUNKTIONIERT NICHT */ /* O.K. */
#include <math.h>
main() main()
{ {
printf("%f", cos(0)); printf("%f", cos(0));
} }
F. Lassen sich Fließkomma-Fehler durch ein Programm abfangen?
A. Die Funktion signal() ist unter anderem für die Behandlung von
Fehlerbedingungen des Emulators und des 8087 bei direkten Befehlen
vorgesehen; die Funktion matherr() für Bereichsüberschreitungen und
unzulässige Argumente bei Routinen der Laufzeitbibliothek. Die ent-
sprechenden Beschreibungen finden Sie im Referenzhandbuch.
L i n k e r
----------------------------------------------------------------------
F. Was hat die Meldung "Linker Error: Unable to open input file 'C0x.OBJ'"
zu bedeuten?
A. Siehe "Integrierte Entwicklungsumgebung" in dieser Datei.
F. Welchen Grund hat die Meldung "Linker Error: Undefined symbol '_main'
in module C0"?
A. Jedes C-Programm muß genau eine Funktion mit dem Namen main
definieren. Diese Funktion wird als "Hauptprogramm" durch den Start-
code aufgerufen.
(Daß der Linker dem Namen _main hier einen Unterstrich voranstellt,
liegt an den allgemeinen Regeln zur Namensgebung in C - main ist
ein global gültiges Symbol).
F. Wieso beharrt der Linker darauf, daß die Funktionen des Grafikpakets
"undefiniert" sind?
A. Siehe "Integrierte Entwicklungsumgebung" und "Kommandozeilen-Version"
in dieser Datei.
F. Was bitte ist ein 'Fixup overflow'?
A. Siehe Benutzerhandbuch, Anhang.
F. Ich habe versucht, eigene Maschinenroutinen in mein C-Programm ein-
zubinden - mit dem Ergebnis, daß diese Routinen für den Linker
sämtlich "undefiniert" sind.
A. Wahrscheinlich haben Sie einen der beiden folgenden Punkte übersehen:
■ C stellt jedem externen Bezeichner einen Unterstrich voran. Eine
Routine, die im C-Quelltext als MyFunc deklariert ist, muß
im Assembler-Quelltext als _MyFunc erscheinen.
■ Die meisten Assembler arbeiten ohne Unterscheidung zwischen Groß-
und Kleinschreibung, solange sie nicht mit einem entsprechenden
Zusatzparameter (für MASM und TASM: /MX) aufgerufen werden - und
für den Linker von Turbo C++ sind _MYFUNC und _MyFunc zwei völlig
verschiedene Dinge.
D i v e r s e s
----------------------------------------------------------------------
F. Wie läßt sich die Standardgröße des Stacks (4096 Bytes) ändern?
A. Die Größe des Bereichs, den Turbo C++ für den Stack reserviert, wird
zur Laufzeit des Programms durch den Wert der globalen Variablen
_stklen festgelegt. Die folgende Deklaration legt beispielsweise
fest, daß der Stack einen Umfang von 10000 Bytes haben soll:
extern unsigned _stklen = 10000;
ACHTUNG: Diese Anweisung darf sich nicht innerhalb einer Funktions-
definition befinden.
F. Mein Programm bricht mit der Meldung 'Stack Overflow!' ab. Was tun?
A. Eine Möglichkeit besteht in einer Vergrößerung des Stacks (siehe
oben); eine weitere in der Deklaration statischer anstelle
dynamischer lokaler Variablen:
main() main()
{ {
char x[5000]; static char x[5000];
/* belegt 5000 Bytes auf /* belegt 5000 Bytes im
dem Stack */ Datensegment */
} }
ACHTUNG: "Speicherung im Datensegment" bedeutet hier auch: diese Variablen
werden bei Rekursion nicht erneut kopiert.
F. Mein Programm gibt nach seinem (anscheinend ordnungsgemäßen) Ende
die beunruhigende Meldung 'Null pointer assignment' aus.
A. Das bedeutet, daß Ihr Programm entweder eine Zuweisung über einen
(vermutlich nicht initialisierten) Zeiger mit dem Wert NULL ausge-
führt oder den Anfang seines Datensegments auf andere Art und Weise
durcheinander gebracht hat.
F. Wieso sind die mit TC.EXE erzeugten .EXE-Dateien größer als bei
einer Compilierung durch die Kommandozeilen-Version?
A. Die integrierte Entwicklungsumgebung bringt standardmäßig
Informationen zur Fehlersuche mit dem integrierten Debugger in der
.EXE-Datei unter (was auf die Ausführungsgeschwindigkeit übrigens
keinen Einfluß hat). Diese zusätzlichen Informationen lassen sich
mit Options/Debugger/Source debugging..None unterdrücken.
F. Der Compiler meldet sich nach einem #include <dos.h> mit
"Declaration syntax error".
A. Sie haben O/C/Source/ANSI keywords only auf ON gesetzt. Dieser Schalter
muß bei Verwendung von DOS.H auf OFF bleiben, weil diese Datei einige
reservierte Wörter enthält, die nicht dem ANSI-Standard entsprechen.
F. Ich habe ein Programm mit dynamischer Speicherverwaltung via malloc()
und/oder calloc() geschrieben, das in den kleinen Datenmodellen
(TINY, SMALL und MEDIUM) anstandslos funktioniert. Wenn ich aber
eines der "großen" Modelle (COMPACT, LARGE oder HUGE) verwende,
hängt sich das System auf.
A. In diesen Modellen liefern malloc(), calloc() usw. FAR-Zeiger zurück -
und deshalb müssen Sie die Datei ALLOC.H mit in Ihr Programm
aufnehmen. Ansonsten erwartet der Compiler den (Standard-)Ergebnistyp
int (= NEAR-Zeiger).
F. Beim Einbinden eines selbstgeschriebenen Maschinenprogramms moniert
der Linker die entsprechenden Symbole als "undefiniert".
A. Siehe "Linker" in dieser Datei.
F. Mit Far-Pointern kann ich nur 64 KByte adressieren. Was tun?
A. Verwenden Sie Huge-Pointer.
F. Kann ich mehr als 64 KByte globaler Variablen deklarieren?
A. In allen Modellen außer HUGE dürfen globale und statische Variablen
des gesamten Programms maximal 64 KByte belegen. Im Modell HUGE
kann jedes Modul bis zu 64 KByte Daten definieren.
F. Wie läßt sich ein Array deklarieren, das mehr als 64 KByte Gesamt-
umfang hat?
A. Arrays mit einem Umfang von mehr als 64 KByte müssen zur Laufzeit
des Programms dynamisch belegt und über HUGE-Zeiger adressiert werden,
sind aber in jedem der "großen Datenmodelle" möglich (d.h. nicht nur
im Modell HUGE). Ein Array, das man normalerweise als
char array[1024][128];
deklarieren würde, wird hier folgendermaßen formuliert:
#include <alloc.h>
char (huge *array)[128]; /* ein HUGE-Zeiger auf ein Array mit
128 Zeigerelementen */
main()
{
array = farcalloc(sizeof(*array), 1024);
}
Der Aufruf von farcalloc belegt für jedes der 128 Elemente des
Arrays 1024 Bytes Platz auf dem Heap. Nach dieser Initialisierung
läßt sich das Array in derselben Weise wie eine statische Variable
adressieren. Eine Zuweisung wie
i = array[30][56];
setzt die Variable i auf den Wert des 31. Elements des 57. Arrays.
F. Wie lassen sich mit Turbo C++ geschriebene Routinen in ein Turbo Pascal-
Programm einbinden?
A. Siehe CPASDEMO.PAS und CPASDEMO.C auf den Originaldisketten in der
Datei EXAMPLES.ZIP. (Sie müssen diese Datei mit UNZIP auspacken).
F. Wie lassen sich mit Turbo C++ geschriebene Routinen in ein Clipper-
Programm einbauen?
A. Falls sich dabei irgendwelche Probleme ergeben sollten, müssen wir
auf die Hotline der Firma Nantucket verweisen.
A l l g e m e i n e s z u C + +
----------------------------------------------------------------------
F. Welche potentiellen Probleme können bei der Typ-Umwandlung eines
Baisklassen-Zeigers in einen Zeiger einer abgeleiteten Klasse
auftreten (damit die Elementfunktionen der abgeleiteten Klasse
aufgerufen werden können)?
A. Syntaktisch ist dies erlaubt. Es ist immer möglich, daß ein Basiszeiger
auf eine Basisklasse zeigt. Wenn es sich um eine Umwandlung in einen
abgeleiteten Typ handelt, existiert unter Umständen die Methode, die
aufgerufen werden soll, in der Basisklasse NICHT. Sie würden daher
die Adresse einer Funktion verwenden, die nicht existiert.
F. Was ist der Unterschied zwischen den Schlüsselwörtern STRUCT und CLASS?
A. Die Voreinstellung für Elemente einer STRUCT ist PUBLIC, für die Elemente
einer CLASS dagegen PRIVATE. Sonst sind sie funktional äquivalent.
F. Ich habe eine von einer Basisklasse abgeleitete Klasse deklariert, kann
aber nicht über die abgeleitete Klasse auf die Basisklassen-Elemente
zugreifen.
A. Abgeleitete Klassen haben NIE Zugriff auf die privaten Elemente einer
Basisklasse. Zugriff ist möglich, wenn die Elemente der Basisklasse als
PUBLIC oder PROTECTED deklariert werden. Wenn sie PUBLIC sind, kann von
jeder Stelle des Programms auf sie zugegriffen werden. Wenn sie PROTECTED
sind, haben die Klassenelemente, Friends und jede abgeleitete Klasse
Zugriff darauf.
F. Wie kann ich die Paradox Engine mit C++ einsetzen?
A. Weil alle Funktionen der Paradox Engine als C-Funktionen kompiliert
sind, müssen Sie sicherstellen, daß die Namen dieser Funktionen nicht
vom C++ Compiler behandelt werden. Die Engine-Funktionen müssen
daher als extern "C" Funktionen definiert werden. Fügen Sie folgende
Zeilen in die Datei pxengine.h an den bezeichneten Stellen ein:
/* An Zeile # 268 einfügen */
#ifdef __cplusplus
extern "C" {
#endif
/* An Zeile # 732, vor dem letzten #endif, einfügen */
#ifdef __cplusplus
}
#endif
F. Ich habe eine Klasse, die von drei Basisklassen abgeleitet ist. Wie
stelle ich sicher, daß ein bestimmter Basisklassen-Konstruktor vor
allen anderen Konstruktoren aufgerufen wird?
A. Wenn Sie die Basisklasse als virtuelle Basisklasse deklarieren, wird
deren Konstruktor vor den anderen (nicht-virtuellen) Basisklassen-
Konstruktoren aufgerufen. Normalerweise erfolgt der Aufruf der
Konstruktoren von links nach rechts, nach der Reihenfolge der
Deklarationen dieser Klasse.
F. Sind die Ein-/Ausgabe-Funktionen der Standard-Library zusammen mit
der C++ iostreams-Library verwendbar?
A. Ja. Funktionen wie printf() und scanf() stehen weiterhin zur
Verfügung, wenn Sie
#include <stdio.h>
angeben.
F. Beim Debuggen mit dem Turbo Debugger ist mir aufgefallen, daß keine
einzige meiner Inline-Funktionen expandiert worden ist. Sie werden
alle wie Funktionsaufrufe behandelt. Was mache ich falsch?
A. Immer dann, wenn Sie ein Programm kompilieren, in dem Debugger-Informa-
tionen stehen, werden die Inline-Funktionen nicht expandiert. Um
klarzustellen, daß die Funktionen korrekt expandiert werden, sollten
Sie mit das Modul mit der Kommandozeilen-Version kompilieren. Benutzen
Sie das Flag -S. Sehen Sie sich danach die generierte .ASM-Datei an.
F. Wenn zwei Variablen mit dem gleichen Namen existieren, eine lokal,
die andere global, wie kann ich dann vom Gültigkeitsbereich der
lokalen Variablen aus auf die global definierte zugreifen?
A. Benutzen Sie den Gültigkeitsbereichszugriffsoperator (::).
int x = 10;
for(int x=0; x < ::x; x++)
{
cout << "Schleife # " << x << "\n"; // wird 10x durchlaufen
}
F. Wird der Compiler die folgenden beiden Funktionen überladen oder
einen Fehler melden? Warum?
void test( int x, double y);
int test( int a, double b);
A. Der Compiler wird einen Deklarationsfehler melden, da weder Argument-
namen noch Typen von Rückgabewerten bei der Bestimmung der Einzig-
artigkeit einer überladenen Funktion eine Rolle spielen. Der Compiler
sieht sich nur die Anzahl und die Typen der Argumente an.
F. Wenn ich einen Character an eine Funktion übergebe, die nur Integer-
Werte akzeptiert, wird der Compiler dann einen Fehler melden?
A. Nein. Der Compiler benutzt die Integer-Repräsentation der Funktion
anstatt das Zeichen selbst und konvertiert den Character-Wert in einen
Integer-Wert.
F. Ich habe versucht, mit Hilfe des Operators new Speicherplatz für ein
Array mit Funktionszeigern zu reservieren, doch ich erhalte nur Syntax-
fehler. Ich benutze folgende Notation: new int (*[10])();.
Was ist falsch?
A. Der Operator new ist ein unärer Operator, der auf das Schlüsselwort
int wirkt und folgendes produziert: (new int) (*[10])();
Schließen Sie also den Ausruck in Klammern ein, und Sie erhalten das
gewünschte Resultat: new (int (*[10])());
F. Was sind bitte Inline-Funktionen? Welche Vorteile haben sie, und wie
sind sie deklariert?
A. Eine Inline-Funktion ist eine Funktion, deren Inhalt (Text) vom
Compiler eingefügt wird. Sie verhält sich ungefähr wie ein Makro.
Der Vorteil ist, daß die Ausführungszeit kürzer wird, da kein
Unterprogrammaufruf stattfindet.
Inline-Funktionen werden folgendermaßen deklariert:
inline void func(void) { cout << "Drucken der Inline-Funktion \n"; }
Oder indem Funktionsdeklaration und Code in einer Klasse einbezogen werden
class test
{
public:
void func(void) { cout << "Inline-Funktion innerhalb einerKlasse.\n"}
};
F. Wenn ich in einer Klasse weder PUBLIC noch PRIVATE spezifiziere, was
ist dann die Voreinstellung?
A. Alle Elemente einer Klasse sind voreingestellt PRIVATE, wenn nichts
anderes angegeben ist.
F. Wozu dient der Modifizierer _seg?
A. Wenn _seg benutzt wird, dann enthält der Zeiger eine Segmentadresse
und keinen Offset. Ein Beispiel:
"int _seg *x" enthält den Wert 0x40. Wenn Sie nun "*x" benutzen, befindet
sich der Wert, auf den der Zeiger zeigt, im Segment 0x40, Offset 0.
Wenn Sie einen Wert zum Zeiger addieren, wird dieser Wert mit der
Größe des Zeigertyps multipliziert. Der neue Wert wird als Offset
genutzt und mit dem Segmentment kombiniert. Ein Beispiel:
int _seg *x;
int value;
x = (int _seg *)0x40;
value = *(x + 20);
Der Variablen value wird der Wert des Integers auf 0x40:0x28 zugewiesen
(Erinnern Sie sich: 20 * sizeof(int) = 40 = 0x28).
F. Kann ich statisch mehr als 64KByte für Daten in einem einzigen Modul
reservieren?
A. Ja. Far-Datenlemente werden nun unterstützt.
...
char far array1[60000L];
char far array2[60000L];
...
Für Arrays größer als 64kByte:
char huge array3[100000L];
F. Wie kann man Hexadezimalwerte in Großbuchstaben über die IO-Stream-
Libraries ausgeben?
A. Benutzen Sie setf() wie im folgenden Beispiel:
#include <iostream.h>
int main(void)
{
cout << hex;
cout << "\nKleinbuchstabe : " << 255;
cout.setf(ios::upper-case);
cout << "\nGroßbuchstabe : " << 255;
return 0;
}
F. Um was handelt es sich bei dem Zeiger "this"?
A. "this" ist eine lokale Variable im Rumpf einer nicht-statischen
Elementfunktion. Es handelt sich um den zeiger auf das Klassenobjekt,
mit dem diese aufgerufen werden. "this" kann nicht außerhalb einer
Klassenelementfunktion verwendet werden.
F. Warum akzeptiert eine binäre Elementfunktion nur ein einziges Argument?
A. Das erste Element ist implizit definiert.
F. Was bedeutet eine Deklaration als "Friend"?
A. Friend bedeutet, daß Elemente, die nicht zu einer Klasse gehören,
trotzdem Zugriff auf die nicht-PUBLIC Elemente dieser Klasse haben.