> Karl ähm .. ich hab da was anderes gelesen ein Array bzw. der
> Bezeichner ist in erster Linie eine Adresse eines Speicherberiches
> und jetzt sag mir mal was dann ein Pointer ist..
Wenn das dort tatsächlich so gestanden hat, dann verbrenne
sofort die Quelle (das Buch) und grab die Asche 3 Meter
tief ein.
Das ist eine der größten Falschinformationen über C.
Ein Array ist kein Pointer!
Ein Array ist ein Speicherbereich in dem Werte gespeichert
werden. Die Sammlung all dieser Werte ist unter dem Namen
des Arrays bekannt.
Ein Pointer seinerseits ist eine ganz normale Variable, die
eine Speicheradresse beinhaltet.
Teil der Konfusion ist sicherlich die übliche Vorgehensweise
den Terminus 'Pointer' für 2 verschiedene Dinge zu verwenden:
* Für eine Variable, die eine Speicher-Adresse enthält
* Für die Speicher-Adresse selbst.
Wie ist es wirklich:
Wird der Name eines Arrays alleine verwendet (also ohne
einen Indizierungsausdruck), so degeneriert der Name des
Arrays zur ersten Speicheradresse des ersten Array-Elements.
(Da fängts schon an: Ich habe bewusst 'erste Speicheradresse
geschrieben. Übliche Ausdrucksweise ist: ... degeneriert zu einem
Pointer auf das erste Array-Element).
Wichtig: Das ganze ist immer noch ein Array und kein Pointer!
Nur weil etwas wie ein Pointer benutzt wird, heist es nicht
das das ein Pointer ist!
Wenn du also hast:
int Tmp[5];
dann degeneriert der Ausdruck 'Tmp' alleine in den meisten
Fällen (eine Ausnahme wäre zb. sizeof) zu einem Pointer auf
das erste Element von Tmp. So zb in
foo( Tmp );
Hier degeneriert Tmp zu einem Pointer auf Tmp[0]. Man könnte
auch salopp sagen, dass 'Tmp' synonym ist zu '&Tmp[0]'
Ein interessanter Punkt in C ist die Art und Weise wie
Array-Zugriffe überhaupt definiert sind. In C ist Array-
Indizierung eine ganz banale Sache. Es ist definiert, dass
der Compiler einen Ausdruck der Form:
a[b]
sofort in die Form
*(a+b)
umformen muss.
d.h. hier kommt wieder der Name des Arrays alleine vor (a) und
daher degeneriet dieser Ausdruck sofort zu ersten Speicheradresse
des Arrays. b ist der Index und wie immer bei Pointer-Arithmetik
wird dbei Addition eines Integer-Typen zu einem Pointer, der
Integer-Typ zuerst mit dem sizeof des Pointer-Quelltyps multipliziert.
Obiges ist daher equivalent zu:
*( ((unsigned char*)a) + b * sizeof( *a ) )
Diese Transformation macht der Compiler intern, wenn er auf einen
Ausdruck
a[b]
stoesst.
Interessant, aber völlig logisch, ist daher, dass man auch
schreiben kann
int a[5];
int b;
b[a]
Der Compiler muss das akzeptieren, da ja dieser Ausdruck
equivalent zu
*(b + a)
ist und Addition kummutativ ist. b + a ist dasselbe wie a + b
Und ob ich jetzt zu einem Pointer einen Integer hinzuzähle oder
zu einem Integer einen Pointer spielt keine Rolle.
Ein Fall an dem es ganz besonders ins Auge geht, dass ein Array
eben kein Pointer ist, ist folgender:
In einer C-Einheit vereinbart man eine globale Variable
int Array[5];
und in einer anderen C-Einheit versucht man Zugang zu dieser
globalen Variable zuerhalten:
extern int* Array;
Das kann so nicht gut gehen. Denn wie gesagt: Ein Array ist
kein Pointer. Im ersten Fall bezeichnet der Name Array einen
Speicherbereich an dem die tatsächlichen int-Werte zu finden sind.
Im zweiten Fall aber wird deklariert, dass Array der Name eines
Speicherbereiches ist, in dem die tatsächliche Speicheradresse
zu finden ist, an dem die int abeleget sind.
In graphischer Form (und irgendwelche Werte für die int angenommen)
Array
+----+----+----+----+----+
| 0 | 20 | 30 | 40 | 10 |
+----+----+----+----+----+
versus
Array
+------+ +----+----+----+----+----+
| o------------------->| 0 | 20 | 30 | 40 | 10 |
+------+ +----+----+----+----+----+
man sieht recht deutlich, dass das 2 vollkommen verschiedene
Dinge sind, auch wenn beide Varianten (und dass ist das perverse
daran) mit vollkommen identischer Syntax beim Zugriff benutzt
werden.
Die richtige Schreibweise wäre im 2-ten Fall
extern int Array[];
und das ist (wie bereits gezeigt) was völlig anderes als
extern int* Array;
Klarer?