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:54:00][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:30]
-
- «-------------------[ 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:52 \ / |/ |/ / |/ / __)__ / | \_/¹
- / | \ | / / / / \ | \
- \_____²_____/____²_________/_________/___________/_____²_____/ö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-
- 7-10
- @END_FILE_ID.DIZ
- /Teil 7/
-
- Kapitel 6
-
- Arrays & Pointer
-
-
- 6.1 Pointer
-
-
- Q6.1.1 Wie verstehe ich Pointer? Sind Pointer Adressen?
-
-
- Praktisch gesehen ja. Praktisch gesehen ist ein Pointer nichts
- anderes als eine Variable, die eine Adresse, d.h. die Nummer
- einer Speicherzelle im Hauptspeicher des Rechners enthält.
- Stellen wir uns vor, wir haben einen Rechner mit 8 MB Haupt-
- speicher. Der Hauptspeicher besteht also aus ca. acht Millionen
- Speicherzellen, die jeweils ein Byte enthalten können. Diese
- Speicherzellen kann man von 0 an durchnumerieren, dann läßt
- sich für alles, was im Speicher steht, feststellen, welche
- Nummer die Speicherzelle hat, wo es steht (bzw. wo es anfängt).
- Wenn z.B. nach der Definition
-
- char z = 'A';
-
- das 'A' in der Speicherzelle Nr. 1234 steht, dann sagt man, die
- Variable z habe die Adresse 1234.
-
- Um die Adresse eines Objekts zu ermitteln, gibt es in C den
- Adreß-Operator "&". In diesem Fall würde
-
- &z
-
- die Adresse von z, also 1234 liefern.
-
- Man könnte auf die Idee kommen, diese Adresse in einer anderen
- Variablen zu speichern, zum Beispiel:
-
- int adr = &z;
-
- Und damit fangen die Probleme an: Wer sagt, daß in einem int
- Platz genug für die Adresse ist? Wenn ein int nur 16 Bits groß
- ist, also keine Werte über 32767 speichern kann, dann kann man
- die Adressen von Objekten, die jenseits der ersten 32 KB des
- Speichers liegen, nicht in einem int ablegen. Also versuchen
- wir es mit:
-
- long adr = &z;
-
- oder
-
- unsigned long adr = &z;
- 40 Arrays & Pointer
- ---------------------------------------------------------------
-
- Aber das bringt nichts, denn auch unsigned long braucht nur
- 32 Bits groß zu sein, was nur für Adressen bis 4 GB reicht.
- (Das erscheint uns heute als eine ganze Menge. Vor zehn Jahren
- erschien uns auch ein Megabyte als eine ganze Menge.) Das
- heißt: auf diese Weise kommen wir nicht weiter, wenn wir mit
- Adressen arbeiten wollen. Aus diesem Grund gibt es in C spe-
- zielle Datentypen, um Adressen von Objekten zu speichern. Diese
- Datentypen nennt man "Pointer" oder "Zeiger". Um möglichst
- flexibel zu sein, definiert C zu jedem Datentyp einen
- Zeigertyp, der Adressen von Objekten dieses Typs halten kann.
- Adressen von chars werden also in "Zeigern auf char" (char-
- Pointern), Adressen von ints in "Zeigern auf int" (int-
- Pointern) usw. abgelegt. Natürlich stellen diese Pointer-Typen
- wiederum Typen dar, so daß es auch auf sie Pointer gibt. Die
- Adresse einer Variablen vom Typ "char-Pointer" kann also in
- einer Variablen vom Typ "char-Pointer-Pointer" abgelegt werden
- usw. Das geht beliebig weit, obwohl mehr als dreifache Pointer
- in der Praxis so gut wie nie vorkommen (und durchaus verhinder-
- bar sind).
-
- Pointer werden durch einen "*" kenntlich gemacht, also:
-
- char z = 'A'; /* ein char */
- char *p = &z; /* ein Pointer auf z */
- char **pp = &p; /* ein Pointer auf p */
-
- Man kann sich einen Pointer also einfach vorstellen als eine
- Variable, die die Adresse eines anderen Objekts speichern kann.
- Auf vielen Systemen sind Pointer daher identisch mit ints oder
- longs, d.h. wenn bei
-
- char z = 'A';
-
- das 'A' an Adresse 1234 liegt, dann haben die beiden Variablen
-
- int i = 1234;
- char *p = &z;
-
- dieselbe interne Darstellung (d.h. sie belegen gleich viel
- Platz im Speicher und stimmen bitweise überein). Allerdings ist
- eine derartig einfache Organisation nicht auf allen Rechnern
- möglich:
-
- - Es gibt Rechner, auf denen Pointer länger sind als ints
- oder longs.
-
- - Es gibt Rechner, auf denen Pointer auf verschiedene
- Typen verschieden viel Platz brauchen.
-
- - Es gibt Rechner, deren Speicher nicht-linear organisiert
- ist.
-
- Mit anderen Worten, wie ein Pointer intern aussieht, läßt sich
- nicht von vornherein festlegen, weil es in großem Maße vom
- verwendeten Prozessor und dem Betriebssystem abhängt. Deswegen
- sind Pointer in C von dem ursprünglichen Konzept der Adressen
- abstrahiert. Pointer stellen einen "abstrakten Datentyp" dar,
- mit dem man arbeiten kann, ohne sich über die interne Organi-
- Arrays & Pointer 41
- ---------------------------------------------------------------
-
- sation bewußt sein zu müssen. Dieser abstrakte Datentyp defi-
- niert auch die Regeln der Pointer-Arithmetik, z.B.
-
- int a[2]; /* ein Array von zwei ints */
- int *p = &a[0]; /* ein Zeiger auf a[0] */
- p++; /* jetzt zeigt p auf a[1] */
-
- Die Pointer-Arithmetik hat ihren Ursprung natürlich in dem ein-
- fachen, linearen Speichermodell, funktioniert aber auch auf
- Rechnern, deren Speicher anders organisiert ist. Das sicher-
- zustellen ist Sache des jeweiligen Compilerautors, der C-Pro-
- grammierer braucht sich nicht darum zu kümmern.
-
- Anfänger in C tun gut daran, sich Pointer wie oben beschrieben,
- also als Variablen, die Adressen speichern, vorzustellen. Auf
- diese Weise versteht man am ehesten, was es mit Pointer-
- arithmetik auf sich hat oder wie Dinge wie Pointer auf Pointer
- funktionieren. Man sollte aber nicht vergessen, daß es sich
- dabei nur um eine Vorstellung handelt, von der man sich irgend-
- wann trennen muß. (wr)
-
-
- Q6.1.2 Kann ich einen Pointer auf eine Funktion in einen
- Pointer auf Daten wandeln?
-
-
- Versuchen kann man es zwar, allerdings ist nicht garantiert,
- daß es funktioniert. Daher sollte man es lassen.
-
- Pointer auf Funktionen und Pointer auf Daten dürfen - ent-
- sprechend dem ANSI-Standard - intern unterschiedlich aufgebaut
- sein. Auf einigen Systemen geht das sogar nicht anders, z.B.
- wenn Funktionen in einem nur-lesbaren Datenbereich ("sharable")
- und Daten in einem schreib-/lesbaren Bereich abgelegt
- werden. (tw)
-
-
- 6.2 Null-Pointer
-
-
- Null-Pointer-Diskussionen treten in der Netzgruppe schon
- nahezu deterministischer auf. Auf einer Rangliste der am
- häufigsten gestellten Fragen dürften sich entsprechende Fragen
- über Null-Pointer ganz weit oben befinden. Würde man eine
- Rangliste der falschen Antworten führen, so findet sich mit
- Sicherheit jeglicher Dummfug über Null-Pointer uneinholbar auf
- dem ersten Platz ("Hätte er geschwiegen wäre er ein Philosoph
- geblieben.").
-
- Warum ist das so? Ehrlich gesagt, ich weiß es nicht so richtig.
- Null-Pointer sind weder kompliziert zu verwenden, noch sind sie
- umständlich definiert oder legen ein irgendwie geartetes
- merkwürdiges Verhalten an den Tag. Sie sind lediglich von
- einem Wust von "Programmierer-Aberglaube" verkleistert, von dem
- ich gerne mal wissen würde, wie er zustande kommt. Insofern ist
- es zwar verständlich, wenn auch unsinnig, daß die folgenden
- Aussagen zu Null-Pointern von Leser in vorherigen Ausgaben
- dieser FAQ heftigst bestritten wurden.
- 42 Arrays & Pointer
- ---------------------------------------------------------------
-
- Nichtsdestotrotz, im folgenden finden sich die Fakten über
- Null-Pointer. Sie sind samt und sonders durch den ANSI-Standard
- ([Ratio], [Schi 93]) belegbar. (tw)
-
-
- Q6.2.1 Ist 0 der Null-Pointer?
-
-
- Nein, das ist 0 nicht. Unter bestimmten Umständen wird 0 jedoch
- zu einer sog. "Null-Pointer-Konstanten".
-
- Jeder konstante, integrale Ausdruck mit dem Wert Null (also
- auch 0) in einem Pointer-Kontext (d.h. an einer Stelle, wo ein
- Pointer stehen soll/muß) ist so eine Null-Pointer-Konstante.
- Ebenso wird ein solcher Ausdruck, der zusätzlich noch explizit
- auf (void *) gecasted wird, eine Null-Pointer-Konstante
- genannt. Es gibt also nicht "die" Null-Pointer-Konstante.
- Sprich
-
- (void *)0
- (void *)(1 - 1)
-
- und auch z.B. ein
-
- (7 - 3 - 4)
-
- an der richtigen Stelle sind allesamt Null-Pointer-Konstanten.
-
- Wenn eine solche Konstante einem Pointer zugewiesen oder auf
- Gleichheit mit einem Pointer getestet wird, wird die Null-
- Pointer-Konstante in einen Pointer auf diesen Typ konvertiert.
- Das Ergebnis der Konvertierung der Konstante (ein Pointer) wird
- Null-Pointer genannt. Beispiel:
-
- char *c;
- int *i;
-
- c = 0; /* 'c' wird der Null-Pointer zugewiesen */
- i = (void *) (10 - (8 + 2)); /* i auch */
-
- Welchen "Wert" besitzt ein Null-Pointer? Dazu Frage
- Q6.2.3. (tw)
-
-
- Q6.2.2 Ist NULL der Null-Pointer?
-
-
- Nein, NULL ist ein Makro, das in <stddef.h> (ANSI C) bzw.
- <stdio.h> (K&R C) definiert ist. Der ANSI-Standard fordert für
- NULL nur, daß das Makro zu einer Null-Pointer-Konstante
- expandiert. Damit sind - entsprechend Q6.2.1 - unter anderem
- folgende Definitionen (und noch viele weitere) für NULL
- zulässig:
-
- #define NULL (void *)0
- #define NULL 0
- #define NULL (void *)(1 - 1) /* umstaendlich, zulaessig */
- Arrays & Pointer 43
- ---------------------------------------------------------------
-
- oder z.B. auch
-
- #define NULL (7 - 3 - 4) /* umstaendlich, zulaessig */
-
- Die gelegentlich geäußerten Behauptungen, daß NULL
-
- - der Null-Pointer sei,
-
- - nur an Pointer auf Daten und
-
- - nicht an Pointer auf Funktionen zugewiesen werden darf,
-
- - unbedingt als 0 oder
-
- - unbedingt als (void*)0 definiert sein muß, usw.
-
- sind samt und sonders falsch, purer Aberglaube und durch
- absolut nichts im ANSI-Standard oder im K&R belegbar. (tw)
-
-
- Q6.2.3 Ist ein Null-Pointer ein Pointer mit allen Bits auf 0?
-
-
- Nein, auch das ist alter, aber falscher Programmierer-
- Aberglaube! Ein Null-Pointer kann zwar ein Pointer mit allen
- Bits auf 0 sein (ist es häufig auch), muß es aber nicht.
-
- Für einen Null-Pointer wird nur gefordert, daß jeder Vergleich
- von ihm mit jedem anderen Pointer auf ein Objekt (z.B. eine
- Variable) oder auf eine Funktion das Ergebnis 'ungleich'
- liefert. Nur ein Vergleich von zwei Null-Pointern darf und muß
- 'gleich' ergeben.
-
- Beispielsweise könnte ein Null-Pointer auch ein Pointer mit
- allen Bits auf 1 sein, wenn nur sichergestellt ist, daß es nie
- einen Pointer auf ein Objekt oder eine Funktion geben kann, bei
- dem auch alle Bits 1 sind.
-
- Übrigens, das ist keine blanke Theorie, es gibt Systeme, bei
- denen ein Null-Pointer nicht aus lauter Null-Bits besteht, z.B.
- weil sich dort ein Pointer aus Segmentnummer und Offset
- zusammensetzt und die Segmentnummer des Prozesses nicht null
- ist. (tw)
-
-
- 6.3 Diverses
-
-
- Q6.3.1 Ist "char *[]" das gleiche wie "char **"?
-
-
- Im Normalfall nicht. char *[] bezeichnet ein Array von Pointern
- auf char und char ** bezeichnet einen Pointer auf einen Pointer
- vom Typ char. Beides ist deutlich etwas Unterschiedliches.
-
- Nun wird unter bestimmten Umständen der Name eines Arrays in
- einen Pointer auf das erste Element das Arrays gewandelt. So
- z.B. bei Funktionsdefinitionen. Daher entspricht
- 44 Arrays & Pointer
- ---------------------------------------------------------------
-
- void funk(char *array[]) { /* ... */ }
-
- einem
-
- void funk(char **array) { /* ... */ }
-
- Dies gilt aber nur dort. Andere Operationen sind nur in einer
- Richtung möglich:
-
- char **p;
- char *a[10];
-
- p = a; /* legal, entspricht 'p = &a[0];' */
- a = p; /* illegal! a ist kein l-value */
-
- (tw)
-
-
- Q6.3.2 Wie initialisiere ich ein mehrdimensionales Array?
-
-
- Im Prinzip nicht anders, als ein eindimensionales Array, mit
- einer Initialisierungsliste. Verwirrend ist häufig nur die
- Reihenfolge der Dimensionen/Elemente. Zu beachten ist, daß die
- letzte angegebene Dimension am schnellsten variiert. Ein
- Beispiel soll dies zeigen:
-
- #define X (2)
- #define Y (3)
- #define Z (4)
-
- int a[Z][Y][X] = {
- /* y = 0 y = 1 y = 2 */
- /* z=0 */ {{ 000, 001 }, { 010, 011 }, { 020, 021}},
- /* z=1 */ {{ 100, 101 }, { 110, 111 }, { 120, 121}},
- /* z=2 */ {{ 200, 201 }, { 210, 011 }, { 220, 221}},
- /* z=3 */ {{ 300, 301 }, { 310, 311 }, { 320, 321}}
- /* ^ ^ ^ ^ ^ ^ */
- /* | |________|____|________|____| x = 1 */
- /* | | | */
- /* |_____________|_____________|_____ x = 0 */
- };
-
- X ist hier die letzte Dimension, variiert also am schnellsten.
- Es bietet sich immer an, als letzte Dimension diejenige mit der
- geringsten Wertigkeit - aus Sicht der Applikation - anzugeben.
-
- Die einzelnen Dimensionen im obigen Beispiel wurden mit '{',
- '}' geklammert um die Übersichtlichkeit zu verbessern.
- Natürlich ist auch
-
- int b[Z][Y][X] = {
- 000, 001, 010, 011, 020, 021,
- 100, 101, 110, 111, 120, 121,
- 200, 201, 210, 011, 220, 221,
- 300, 301, 310, 311, 320, 321
- };
-
- zulässig. (tw)
- 46 Arrays & Pointer
- ---------------------------------------------------------------
-
- /Ende von Teil 7/
-
- 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:30]
-
- «-------------------[ 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·
-
-