Ich probier hier mal von den internen Aufbau eines Arrays auf die Pointer zu kommen, so (finde ich zumindest) ist das die beste und einleutendste Handhabung. Am Ende komme ich dann auf die Beantwortung des Problemes zurück.
Also hier ist der interne Aufbau eines Array an Speicherzellen:
In den Eckigen Klammern stehen die Werte, eine einzelne Zelle wird durch [] repräsentiert
|
Quellcode
|
1
2
|
0x00 0x07
[][][][][][][]
|
Das ist ein Array was von Adresse 0 bis 7 geht. Dazu sind die Adressen angegeben mit der man jedes einzelne Feld erreicht. In unserem Beispiel geht es von Adresse 0 bis 7. Was nun da drin steht, sei erstmal unwichtig.
Nun kommen wir zu der Bedeutung des Pointers. Unser Array kann ja nicht immer an Adresse 0 liegen, da wir erstens auch mehr als ein Array haben wollen und wir ja nicht nur ein Programm haben was läuft.... Wir haben ja auch noch Windows laufen, verschiedene Interrupts, die das OS verarbeitet, den Programmcode und so weiter... einfach gesagt es kann nicht immer an Adresse 0 liegen.
So kommen wir zu folgender Darstellung:
(Hinweis pArray zeigt nur auf das erste Element!)
|
Quellcode
|
1
2
|
0x30 0x37
pArray -> [][][][][][][]
|
Die neu eingefügte Größe heist nun pArray. Diese soll uns den Beginn des Arrays zeigen. pArray ist also eine Adresse im Speicher. In unserem Beispiel ist diese 0x30h. Um die Zuweisung dieser Adresse soll sich jetzt aber das OS kümmern, wir haben was anderes vor
. Mit diesem Lösungsansatz ist es jetzt mgl. den Speicher mit Arrays vollzupumpen. Jedes könnten wir unterscheiden, da jedes eine Variable, genauer eine Adresse hat die wir kennen.
So, wir können jetzt unser Array folglich auch voll durchlaufen, wir haben den Anfang... also 0x30 und können diesen incrementieren... also ist folgender C++ Ausdruck gültig: ++pArray++;
pArray würde jetzt auf 0x32 zeigen.
Damit wir den Wert auch auslesen können, haben wir den tollen * Operator. Wir können also folglich alle Werte so auslesen: *(++pArray++) Sieht vllt. etwas kryptisch aus, ist aber vollkommen logisch... hier ein Beispiel:
|
C-/C++-Quelltext
|
1
2
3
4
|
for(unsigned i=0; i < 7;i++)
{
printf("%d ", *(pArray + i));
}
|
Das funktioniert könnt ihr probieren, da aber das schreiben eines solchen Ausdruckes *(pArray + i) viel zu lang dauert, nimmt man kurzerhand pArray
, was aber zu dem von uns SELBST ERMITTELTEM vollkommen kongruent ist. d.h.: *(pArray + i) = pArray[i]
Wenn wir also sagen:
|
Quellcode
|
1
2
|
char* pArray;
pArray = "Hallo";
|
ist das völliger Stuss. pArray ist ja der Anfang unseres Arrays, eine Adresse... und "Hallo" ist ja nun weiss Gott keine Adresse.... sondern ein WERT
Wieso funktioniert dann aber das?
|
Quellcode
|
1
|
char pArray[] = "Hallo";
|
Hmmn, wer Assembler kann dem wird gleich auffallen, das das ganz logisch ist, wie eigentlich alles . Der String "Hallo" wird dann in sowas wie einem Datensegment gespeichert, wo alle Konstanden hinkommen. Wenn Hallo dort plaziert wird, haben wir auch eine Adresse die auf Hallo ziegt, und diese Adresse kopieren wir eigentlich mit diesem Schritt.
Und wie gibt uns nun das OS Speicher?
Man unterscheidet dynamischen (während der Laufzeit des Programmes allociierten Speicher) und statischen Speicher (der während des Startens bereits reserviert wird). Mit
|
C-/C++-Quelltext
|
1
|
new
|
können wir neuen Speicher Anfordern, der uns dann eine Adresse zurückgibt, die wir aber mit
|
C-/C++-Quelltext
|
1
|
delete
|
wieder freigeben müssen. Staisch machen wir das einfach so:
|
C-/C++-Quelltext
|
1
|
char pArray[56];
|
Unser Array ist so unveränderlich 56 char Einheiten groß.
strcpy bzw. wcscpy nehmen sich jetzt jede Array Zelle her und kopieren dort einen Byte [8Bit] (ANSI) oder Word [16Bit](UNICODE) Wert hinein.