home *** CD-ROM | disk | FTP | other *** search
- _______________ _____ _____ _________ ___________________
- \. /________ |. /_____:o | /. \/|___/_ \ /
- \___ _____/|. / \|| /|. |: |// ______/·|. / ______ \ ___/
- /. /_/· || / \: \|| |· |/ / \ \/ || /_______ \/+ /
- // ____/ || \ \ \ \: ¯¯¯ | / / / || \ /·\ / \ __/_
- // / // |+ \ \ \ \___/ | \___/ / |· \/ \/ / /
- /· / \\ / \ / |: | / / / /
- \___/ \________/_____|\___/: |_____|_______/\________/_______/______/
- l_____|·MBB·
-
-
- _ ___ \ _
- ___|__________/\______\//\________________________________________________ _
- \___ / ___/ \_____\//\______________ /\ ______/ _______/ ___ _
- | _/ \ _ \_ \/ | ___)_/_ ___/_/_ ___)_\______ \______
- | \ \/ / || | \ | \ | \ / / /
- _ __| \__________/____|| |____ |__ |__ _____/ ___ _
- `----' `-----' `------' `------' `---------' `------'
-
- [hOMELESS÷bBS!]
-
- [bIRDHOUSE^pROJECTS eUROPEAN hQ][mYTH! gERMAN hQ][aRT-cORE! fUN hQ]
-
- [sYSdOODE: -sLIME!^bIRDHOUSE÷pROJECTS-lEADER^mYTH!]
- [cOdOODES: mOGUe!/sCX^aC! pRIMUS!/bP!-lEADER]
- [MR.VAiN/bNZ^aC! wHIRLWIND/mYTH!]
-
- [uPLOADER:GeNeRaTioN ][oF:[+] PRODIGY '95 [+]]
- [uPLOAD tIME:13:53:20][uPLOAD dATE:03-Jan-95]
-
- _ ___ \ _
- ___|__________/\______\//\________________________________________________ _
- \___ / ___/ \_____\//\______________ /\ ______/ _______/ ___ _
- | _/ \ _ \_ \/ | ___)_/_ ___/_/_ ___)_\______ \______
- | \ \/ / || | \ | \ | \ / / /
- _ __| \__________/____|| |____ |__ |__ _____/ ___ _
- `----' `-----' `------' `------' `---------' `------'
-
-
-
-
- «------------------[ eLITE gUYS wILL gET iNVITED hERE ]------------------»
- . . . . : · .
- ____/¦__ ___/¦____ __/¦___________/¦__ ¦ ¦___/¦__ !
- _ ____ \__\____ _// _____\_________ \ | | ____ \__ _:/\__
- /· |____//· | \\_____ ·\| | | \\| |/· |____/ \ Oo /
- // | \ | \ l \\ | | ·\_ // | \ /_--_\
- \__________\________/________/___j___j / \__________\ :\/
- -------------------------------------l____/ :----------- ¡
- · ·
- . : · . . . .
- ! _ ____/¦__ ¦ ¦____¦\____ ____/¦__ ___/¦____ __/¦_____ __
- _:/\__ _ _ ____ \__| |______ \ _ ____ \__\_ | _// _____ __ _
- \ Oo / /· |____/| |/· __ __/ /· |____//· | \\_____ ·\
- /_--_\ // | \| // | \_// | \ l \ l \\
- :\/ \__________\ \____j /\__________\________/________/
- ¡ -----------· :----l____/-------------------------------
- · ·
- <*> pRODIGY gHQ <*> nEUTRON wHQ <*> iLLUSION eHQ <*> dYNAMIX gHQ <*>
-
- Upload Date: [01-03-95] «» Upload Time: [07:18:21]
-
- «-------------------[ aSK eLITE fOR SYS-PW & NUMBA ! ]-------------------»
-
- .__ _ r
- : __tHIS fILE wAS D/L fROM I
- _ _02-Jan-95_________________________: N
- _| \/ | G
- \/ T¾R¾S¾I LEADER H¾Q \\ ² tRISTAR & rED
- \ sECTOR
- ö . |_/\________/\__.___ _/\_______ | W
- /\ |\ ._ \ \ \ ____)² iNC.
- . \/\------------|/ |/____/ \ / __)__!---------------.
- |\/ / ² / | \ \ 4nODEZ |
- | \_____| \_____²_____/___________/ !_
- |ö | | /_/\
- | _/\__.___ !/\_._/\________/\________/\______! _/\______ \_\/
- | \ \ \___!\ ._ \ ._ \ ____) \ . \ |
- 00:13:23 \ / |/ |/ / |/ / __)__ / | \_/¹
- / | \ | / / / / \ | \
- \_____²_____/____²_________/_________/___________/_____²_____/ö2Fö
- ² ²
- _!/\__ |__
- \ Oo / +49 p¾R¾I¾V¾A¾T¾E¾! ___| /
- eLITE gUYS /_--_\ \ //
- wILL gET ²\/ tHE hOLY mASTER iS \/|
- iNVITED hERE ! mClOUD ²
- ² aND hIS hELPING hAND iS mARIO :
- :
- ¾ aSK fOR nUMBER aND sYSPW/nUP
-
-
- @BEGIN_FILE_ID.DIZFREQUENTLY ASKED QUESTIONS ABOUT `C`
- -German Edition-
- 5-10
- @END_FILE_ID.DIZ
- /Teil 5/
-
- Q3.2 Was ist ein Prototyp?
-
-
- Prototypen wurden mit ANSI C eingeführt, sie sind eine
- spezielle Form der Deklaration von Funktionen (allerdings ist
- nicht jede Deklaration einer Funktion ein Prototyp).
-
- Im Unterschied zur alten Form der Deklaration einer Funktion
- enthält die neue Form (die Prototypen-Form) auch die
- Argumenttypen:
-
- int func1(); /* K&R Deklaration */
-
- int func2(int i, char *s); /* ANSI Prototyp */
-
- Nur die Deklaration von func2() nennt man einen Prototypen für
- func2(), die Deklaration von func1() ist genau das, was sie
- schon immer war: eine Deklaration.
-
- Auch wenn ANSI C die alte Form der Deklaration noch zuläßt,
- sollte man immer Prototypen verwenden. Dies ermöglicht dem
- Compiler, Aufruf-Fehler zu erkennen, und erleichtert evtl.
- Optimierungen. In einem Fall muß man sogar die Prototyp-Form
- Deklarationen, Definitionen, Prototypen 25
- ---------------------------------------------------------------
-
-
- verwenden: Bei Prototypen gibt es mit '...' die Möglichkeit,
- Funktionen mit variabler Argumentliste explizit zu deklarieren.
- Eine solche Deklaration ist in ANSI C nicht optional, sie muß
- mit '...' erfolgen (siehe dazu Q3.4 und Q4.1). In K&R C gibt es
- dafür keinen Sprachkonstrukt. Allerdings lassen sich auch in
- K&R C Funktionen mit variabler Argumentliste programmieren,
- siehe ebenfalls Q4.1.
-
- Schreibt man eine Header-Datei, die sowohl mit einem K&R-
- also auch mit einem ANSI-Compiler verwendet werden soll, so
- kann man sich mit Hilfe des Preprozessors aus der Affäre
- ziehen. Eine Möglichkeit ist:
-
- #ifdef __STDC__ /* ANSI Prototypen */
- void f1(int i);
- int f2(double d);
- #else /* K&R Deklarationen */
- void f1();
- int f2();
- #endif
-
- Da man bei obiger Form alle Funktionsdeklarationen doppelt
- schreibt, findet man häufig auch:
-
-
- #ifdef __STDC__ /* ANSI Prototyp */
- # define P(x) x
- #else /* K&R Deklaration */
- # define P(x) ()
- #endif
-
- void f1 P( (int i) );
- int f2 P( (double d) );
-
- ...
-
- #undef P
-
- Das abschließende #undef P ist nicht unbedingt nötig, es
- vermeidet eventuelle Konflikte nur teilweise. (tw)
-
-
- Q3.3 Wie lese ich komplexe Deklarationen?
-
-
- Um Deklarationen zu lesen, muß man die sogenannten
- "Deklaratoren" kennen. Deklaratoren sind eigentlich nichts
- besonderes, sie sind die Gegenstücke zu den Operatoren. Dazu
- ein Beispiel:
-
- Bei der Deklaration
-
- int array[];
- 26 Deklarationen, Definitionen, Prototypen
- ---------------------------------------------------------------
-
-
- ist [] ein Deklarator (genauer: der Array-Deklarator). Wird nun
- auf ein so deklariertes Array zugegriffen, dann geschieht dies
- z.B. in der Form
-
- j = array[0];
-
- Hier ist [] jetzt der Array-Subscription Operator.
-
- Warum dieses Beispiel? Um Deklarationen zu lesen, benötigt man
- die Bindung und den Vorang der Deklaratoren. Dummerweise findet
- man jedoch in praktisch keinem Lehrbuch eine entsprechende
- Liste. Zum Glück geht es auch ohne, da Deklaratoren die gleiche
- Bindung und den gleichen Vorrang wie die entsprechenden
- Operatoren besitzen. Man kann also die in jedem halbwegs
- brauchbaren Lehrbuch enthaltene Tabelle mit den Operatoren
- verwenden.
-
- Kennt man diese, dann kann man (komplexe) C-Deklarationen von
- innen nach außen lesen. Angefangen wird beim Objektnamen (dem
- Namen der Funktion oder Variable). Von da arbeitet man sich
- - unter Berücksichtigung des Vorrangs und der Bindung der
- Deklaratoren - nach außen vor.
-
- Die gesamte Bedeutung der Deklaration wird dabei stückweise
- zusammengesetzt. Dazu benötigt man folgende "Textbausteine":
-
- name "'name' ist"
-
- * "Pointer auf"
-
- (...) "Funktion mit den Parametern ... und dem Rückgabetyp"
-
- [...] "Array von ..."
-
- Datentyp "Datentyp"
-
- Das Ergebnis muß man üblicherweise noch etwa "weichspülen", um
- ein erträgliches Deutsch zu erhalten.
-
- Beispiele:
-
- Die Bedeutung von
-
- char **var[];
- /* ^ ^^ ^ ^ */
- /* 5 43 1 2 */
-
- erhält man in folgenden fünf (bzw. sechs) Schritten:
-
- 1. Objektname:
-
- 'var' ist
-
- 2. '[]' hat Vorrang vor '*':
-
- 'var' ist Array von
- Deklarationen, Definitionen, Prototypen 27
- ---------------------------------------------------------------
-
-
- 3. Innerer '*':
-
- 'var' ist Array von Pointer auf
-
- 4. Zweiter '*':
-
- 'var' ist Array von Pointer auf Pointer auf
-
- 5. Datentyp 'char':
-
- 'var' ist Array von Pointer auf Pointer auf char
-
- 6. "Weichspülen":
-
- 'var' ist ein Array von Pointern auf Pointer auf
- char.
-
- Für folgende Deklaration
-
- char *(*a)[];
- /* ^ ^ ^^ ^ */
- /* 5 4 21 3 */
-
- erhält man so:
-
- 1. Objektname:
-
- 'a' ist
-
- 2. Aufgrund der Klammerung hat der innerer '*' Vorrang vor
- '[]':
-
- 'a' ist Pointer auf
-
- 3. '[]' hat Vorrang vor dem zweiten '*:
-
- 'a' ist Pointer auf Array von
-
- 4. Der äußere '*':
-
- 'a' ist Pointer auf Array von Pointer auf
-
- 5. Datentyp 'char':
-
- 'a' ist Pointer auf Array von Pointer auf char
-
- 6. Schöneres Deutsch:
-
- 'a' ist ein Pointer auf ein Array von Pointern auf
- char.
-
- Wenn man sich das Schema partu nicht merken will oder kann,
- dann ist das auch nicht so schlimm: Es gibt Programme dafür.
- Beispielsweise findet sich in [K&R II 88] ein Programm namens
- "dcl". Es ist zwar ein furchtbarer C-Hack, aber dafür nur ca.
- 100 Zeilen "lang". (tw)
- 28 Deklarationen, Definitionen, Prototypen
- ---------------------------------------------------------------
-
-
- Q3.4 Warum soll man Funktionen mit variabler Argumentenliste
- (wie z.B. printf()) nicht ohne Prototypen aufrufen?
-
-
- Der Aufruf einer Funktion mit variabler Argumentenliste ohne
- vorliegenden Prototypen führt zu undefiniertem Verhalten. Der
- Grund dafür ist, daß es Compilern erlaubt ist, verschiedene
- Aufrufkonventionen für Funktionen zu verwenden, z.B.:
-
- - Parameterübergabe in Registern für Funktionen mit fester
- Argumentenliste (schnell, aber nicht für beliebig viele
- Parameter geeignet) und
-
- - auf dem Stack für Funktionen mit variabler Argumenten-
- liste (langsam, geht aber mit beliebig vielen
- Parametern).
-
- Meist wird obige Unterteilung - und keine Mischform -
- verwendet, da z.B. va_arg() exterm kompliziert (bei einigen
- Prozessoren sogar unmöglich) wäre, wenn die Parameter teils in
- Registern, teils auf dem Stack liegen würden.
-
- Das macht es aber notwendig, daß der Compiler beim Aufruf einer
- Funktion immer wissen muß, auf welche Weise diese die Parameter
- verlangt. In K&R C, wo über die Parameter nichts bekannt war,
- mußte er stets vom schlimmsten Fall ausgehen und konnte daher
- keine optimierte Registerübergaben durchführen. In ANSI C gibt
- es Prototypen, und wenn ein Prototyp vorliegt, weiß der
- Compiler, ob die Funktion feste oder variable Argumentenliste
- hat, und kann so die richtige Aufrufkonvention verwenden.
-
- Und wenn kein Prototyp vorliegt? Dann geht der Compiler davon
- aus, daß die Argumentenliste unbekannt, aber fest ist, d.h. es
- wird die Aufrufkonvention für feste Argumentenlisten
- verwendent, was aber schiefgehen kann, falls diese mit der
- Aufrufkonvention für variable Argumentenlisten inkompatibel
- ist.
-
- Deswegen die Festlegung: der Aufruf einer Funktion mit
- variabler Argumentenliste ohne vorliegenden Prototypen führt zu
- undefiniertem Verhalten.
-
- Das ist nicht bloße Theorie, z.B. funktioniert mit PureC auf
- dem Atari (der o.a. zwei Aufrufkonventionen unterstützt) ein
- printf() ohne den Prototypen aus stdio.h nicht.
-
- Auch Compiler, die immer eine Mischform bei der
- Parameterübergabe verwenden, können böse ins Straucheln kommen.
- Ein älterer C-Compiler eines bekannten Unix-Betriebssystems
- hatte eine interessante Eigenschaft: Die ersten drei Parameter
- (wenn sie je 32 Bit groß waren) wurden immer in Registern, der
- Rest auf dem Stack übergeben. Damit im Extremfall (Funktion mit
- falscher Parameterliste gerufen) wenigstens die Stackgröße
- stimmte, wurden zusätzlich drei "Dummy-Argumente" a 32 Bit auf
- den Stack gelegt. Für va_arg() gabe es eine Ausnahme: die
- Register-Werte wurden, damit alle Parameter einheitlich gelesen
- werden konnten, in die "Dummy-Argumente" auf dem Stack kopiert.
- Das Ergebnis war ein einziges Chaos: Wenn man auch nur den
- Deklarationen, Definitionen, Prototypen 29
- ---------------------------------------------------------------
-
-
- kleinsten Fehler machte, erhielt eine gerufene Funktion zu
- Anfang mal drei leere Argumente, mal fehlten drei... (wr)
-
-
- Q3.5 Wie sieht ein korrekt getyptes C-Programm aus?
-
-
- Es gibt C-Programmierer, vor allem solche, die sich vorher mit
- Sprachen wie Pascal (die über ein sehr strenges Typkonzept
- verfügen) beschäftigt haben, die Wert darauf legen, ihre C-
- Programme "korrekt getypt" zu formulieren, z.B. so:
-
- int i;
- long l;
- char *p = (char*)NULL;
-
- i = (int)'A';
- l = (long)i + 12L;
-
- printf("%c\n",(char)i);
-
- Dieser Stil zeichnet sich durch exzessive Verwendung von Casts
- aus, die dafür sorgen sollen, daß alle Ausdrücke stets nur die
- erwarteten Datentypen verwenden.
-
- Allerdings hat dieser Stil mehr Nach- als Vorteile. "Korrekt
- getypt" im Sinne von C ist nämlich auch:
-
- int i;
- long l;
- char *p = NULL;
-
- i = 'A';
- l = i + 12;
-
- printf("%c\n",i);
-
- Die notwendigen Umwandlungen (z.B. die von i+12 in long) werden
- vom Compiler automatisch durchgeführt. Durch das Verzichten auf
- Casts werden die Programme lesbarer, und der Compiler kann bei
- möglichen Problemen eine Warnung ausgeben.
-
- long l = 0xabcdefL;
- int i = (int)l;
-
- Angenommen, ein int ist 16 und ein long 32 Bits groß, dann kann
- die Zuweisung an i nicht ohne Verluste vonstatten gehen (da
- 0xabcdef nicht in 16 Bits paßt). Der Cast in der Zuweisung
- jedoch führt eine explizite Typumwandlung durch, so daß der
- Compiler die verlorene Genauigkeit nicht feststellt (oder davon
- ausgeht, daß der Programmierer sie beabsichtigt oder in kauf
- nimmt). Ohne den Cast könnte der Compiler eine Warnung (in der
- Art "loss of significance") ausgeben.
-
- Das gleiche gilt für fast jeden Kontext, in dem Objekte ver-
- schiedener Datentypen zusammen verwendet werden. Die von C
- durchgeführten impliziten Datentypumwandlungen arbeiten in den
- meisten Fällen wie gewünscht, so daß zusätzliche Casts keinen
- 30 Deklarationen, Definitionen, Prototypen
- ---------------------------------------------------------------
-
-
- Gewinn bringen, sondern höchstens Warnungen unterdrücken und so
- Fehlerquellen darstellen. Außerdem sollte man beachten, daß
- (siehe erstes Beispiel) weder 'A' ein char ist noch %c in
- printf() ein char erwartet.
-
- Explizite Typumwandlungen sind notwendig, wenn man
-
- - die standardmäßigen Umwandlungsregeln umgehen möchte
- oder muß. Z.B. wird in
-
- int a, b;
- long l = a * b;
-
- zuerst a*b als int berechnet und das Ergebnis in long
- umgewandelt. Bei der Multiplikation kann ein Überlauf
- auftreten, der das Ergebnis verfälscht und der mit
-
- int a, b;
- long l = (long)a * (long)b;
-
- vermieden werden könnte,
-
- - Werte an Funktionen mit variabler Argumentenliste
- übergibt, da hierbei kein Zuweisungskontext besteht und
- daher keine automatische Typumwandlung stattfinden kann.
- Die Casts in
-
- long l = 'A';
- printf("%c %ld %p\n",(int)l,(long)sizeof(l),(void*)&l);
-
- sind also notwendig.
-
- Zusammenfassend kann gesagt werden, daß man auf Casts soweit
- wie möglich verzichten sollte. C hat ein Typkonzept, wenn auch
- ein liberales. Es hat keinen Zweck, die Regeln von Programmier-
- sprachen mit strengeren Typkonzepten auf C übertragen zu wollen
- und deswegen auf die Vorteile des liberalen Typkonzepts zu ver-
- zichten. (wr)
-
- /Ende von Teil 5/
-
- Keep hacking
- Wolfram
-
-
-
-
- «------------------[ eLITE gUYS wILL gET iNVITED hERE ]------------------»
- . . . . : · .
- ____/¦__ ___/¦____ __/¦___________/¦__ ¦ ¦___/¦__ !
- _ ____ \__\____ _// _____\_________ \ | | ____ \__ _:/\__
- /· |____//· | \\_____ ·\| | | \\| |/· |____/ \ Oo /
- // | \ | \ l \\ | | ·\_ // | \ /_--_\
- \__________\________/________/___j___j / \__________\ :\/
- -------------------------------------l____/ :----------- ¡
- · ·
- . : · . . . .
- ! _ ____/¦__ ¦ ¦____¦\____ ____/¦__ ___/¦____ __/¦_____ __
- _:/\__ _ _ ____ \__| |______ \ _ ____ \__\_ | _// _____ __ _
- \ Oo / /· |____/| |/· __ __/ /· |____//· | \\_____ ·\
- /_--_\ // | \| // | \_// | \ l \ l \\
- :\/ \__________\ \____j /\__________\________/________/
- ¡ -----------· :----l____/-------------------------------
- · ·
- <*> pRODIGY gHQ <*> nEUTRON wHQ <*> iLLUSION eHQ <*> dYNAMIX gHQ <*>
-
- Upload Date: [01-03-95] «» Upload Time: [07:18:21]
-
- «-------------------[ aSK eLITE fOR SYS-PW & NUMBA ! ]-------------------»
-
- [-AquaAdder v1.0-]
-
-
-
-
-
-
- -sLiME!^bP·LEADER^mTH!
- mOGUe!^aC! pRIMUS!/bP·lEADER
- wHIRLWIND/mTH! MR.VAIN/BNZ^sXi^aC!
-
- -- --- ---- pHUKKIN' fAST aMIGA ^ wORLD'S lARGEST cHIPTUNE aREA ---- --- --
- ____
- ___| |_____________ __________________ ____________________________
- _/ _| | ._________\/__________ \ _/___\______ \ _____/ _____/
- \ \. | l/ / \/ | _____/_ l / _____/\____ _/\____ \_
- \___| |________/____||-Mo!|________________/_______\ _______\ ________/
- l____| l____| \/ \/
-
- -- --- ---- aMI-eX fREE-lEECH ^ bIG aSCII bASE © bY aC! ---- --- --
-
- -- mYTH! gHQ - -÷- - bIRDHOUSE pROJECTS! eHQ - -÷- - aRT-cORE! eHQ --
-
- _______________ _____ _____ _________ ___________________
- \. /________ |. /_____:o | /. \/|___/_ \ /
- \___ _____/|. / \|| /|. |: |// ______/·|. / ______ \ ___/
- /. /_/· || / \: \|| |· |/ / \ \/ || /_______ \/+ /
- // ____/ || \ \ \ \: ¯¯¯ | / / / || \ /·\ / \ __/_
- // / // |+ \ \ \ \___/ | \___/ / |· \/ \/ / /
- /· / \\ / \ / |: | / / / /
- \___/ \________/_____|\___/: |_____|_______/\________/_______/______/
- l_____|·MBB·
-
-