Hi!
Ich habe mal eine Frage zu Pointern. Und zwar wie spreche ich damit
mehrdimensionale arrays an?
Wenn ich zum Pointer auf ein normales Array z.B. 1 dazuaddiere, dann
komm ich ja aufs selbe raus, als wenn ich array[1] geschrieben hätte.
Aber was passiert wie gesagt bei beispielsweise 2 dimensionalen Arrays.
Da gibt es einen ganz tollen Effekt, der das Arbeiten mit Pointern und
mehrdimensionalen array´s erheblich vereinfacht. Und zwar speichert der
Computer normale als auch mehrdim. A. im Speicher hintereinander ab und
zwar wenn Du ein 3x4 Array hast, dann kommt die erste Zeile mit 4
Werten, gleich danach die zweite mit 4 Werten danach die dritte. Du
läufst also mit dem Pointer durch den Speicherbereich.
Lässt sich daher auch alles mit ner kleinen Schleife erledigen.
Achte aber bitte drauf, dass dein Pointer den gleichen Typ hat wie dein
Array sonst kommt Müll raus (ist leider ein oft gemachter Fehler der mir
auch ab und an passiert).
Gruß Axel
ist aber zum Erklären ein schreckliches Beispiel. Solche Codes helfen
keinem die Problematik mit Pointern zu verstehen!
Ausserdem bekommt die Funktion eine Adresse übergeben und keinen
Pointer!
Also nicht ganz richtig.
Ein Pointer hat als Inhalt eine Adresse (er wird ja auch anders
deklariert z.B. int *ptr;) und der Vektor
m[0][0] ist in Wahrheit die Anfangsadresse des zweidimensionalen Vektors
die einem Pointer mittels
ptr = m[0][0]; übergeben wird.
Aber kein Pointer! Sonst müsste ich ja den Inhalt von m auch mit dem
Dereferezierungsoperator * ansprechen können.
Ich bin leider so wehement, weil ich aus diesem Grunde früher die Dinge
mit dem Pointer und den Arrays auch nicht verstanden habe. Dass es eine
enge Bindung zwischen Pointern und Array´s gibt ist richtig, man darf
Sie aber nicht gleichsetzen sonst versteht man die Materie leider gar
nicht.
Hat man das Pointerproblem gelöst, dann kommt man automatisch auf die
Axel, ich glaube nicht dass Jörg Nachhilfe in Sachen Zeiger braucht ;-)
Irgendwas haust du da durcheinander.
"m[0][0] ist in Wahrheit die Anfangsadresse des zweidimensionalen
Vektors"
m[0][0] ist sicher keine Adresse sondern der erste Wert im Array.
m bzw. a lässt sich prima mit dem Dereferenzierungsoperator verwenden,
allerdings musst du ihn 2 Mal angeben, da du beim ersten Mal nur einen
Zeiger auf das "Unterarray" bekommst.
Du irrst dennoch. Die Funktion bekommt in der Tat nur einen
Pointer übergeben. Für einen Funktionsparameter, der auf ein
Array zeigt, gibt es immer auch eine alternative, vollständig
kompatible Schreibweise, ihn als Zeiger auszudrücken. Daher
ist es auch völlig äquivalent, ob man
int main(int argc, char **argv)
oder
int main(int argc, char *argv[])
schreibt.
Aber ich gebe Dir natürlich völlig recht, daß das von Oliver
gewählte Beispiel eher ungünstig zur Verdeutlichung der
Problematik ist.
@all!
Ich habe das Gefühl, alle anwesenden haben noch nie Pointer auf
mehrdimensionale Arrays einer Funktion übergeben. Ich sehe hier keinen
weiteren Lösungsvorschlag für unseren Androiden.
Steht die Dimension und Größe fest, kann sie direkt in der
Funktionsdefinition festgeschrieben werden. Will man der Funktion
mehrdimensionale Arrays übergeben, dessen Größe variabel sein sollen, so
sieht das allgemein für ein dreidimensionales Array so aus:
void test(int*** m, int dim1, int dim2, int dim3)
{
for (int i = 0; i<dim1;i++)
for (int j = 0; j<dim2;j++)
for (int k = 0; k<dim3;k++)
{
// Zugriff durch
((int*)m)[i * dim1 *dim2 *dim3 +j *dim3 +k]
}
}
Ist das vielleicht ein besseres Beispiel ;-)
Grüße
Oliver
@Andreas
korrekt, Deine Aussage. m stellt hier aber die Anfangsadresse dar:
m und &m[0][0] sind hier gleichwertig.
Da habe ich mich vertan sorry. Ich sage ja auch ich mache Fehler.
@Oliver
Erkläre LtData doch was Du meinst. Oder hast Du C anhand von purem
Sourcecode gelernt. Ausserdem fehlt mir bei deinem etwas Kommentar.
Und ein besseres Beispiel zur Erklärung der Frage ist dein letztes
definitv nicht.
Hallo!
Erstmal vielen Dank an euch alle! Eigentlich hätte ich nur die erste
Antwort von Axel gebraucht (ich hatte mir nämlich schon überlegt, daß
die Daten ja schliesslich im Speicher irgendwie hintereinander kommen
müssen, konnte aber nicht rausfinden ob nun zeilen- oder spaltenweise),
aber insbesondere Olivers letztes Posting hat doch ganz erheblich zum
Verständnis der Zusammenhänge zwischen Pointern und Arrays beigetragen
(auch wenn ich mir das erstmal genau ansehen musste, um das auch zu
verstehen ;-)).
Ich denke mal, auf die Verwendungsmöglichkeiten wäre ich sonst nicht
gekommen. In meinem C++ Buch steht nämlich leider nix über Pointer auf
mehrdimensionale Arrays drinnen.
Nochmals Vielen Dank für die nette Hilfe!
Nein, das ist sogar ziemlicher Quatsch. Wofür übergibst Du
einen int ***, wenn Du ihn dann doch nur auf int * casten
willst? Auch die Multiplikation macht implizite Annahmen über
das Layout des Arrays, die inkorrekt sind.
Hier mal ein witziges Beispiel, das C99-Syntax mit variable-length
arrays benutzt (die der aktuelle gcc aber durchaus kann).
#include <stdio.h>
char
arry[2][3][6] = {
{
"Hello",
"world",
"foo!"
},
{
"Thats",
"some",
"crap!"
}
};
char
get(int a, int b, int c, char x[a][b][c])
{
return x[1][2][3];
}
int
main(void)
{
printf("char = %c\n", get(2, 3, 6, arry));
return 0;
}
In einem hast Du Recht
((int*)m)[i * dim1 *dim2 *dim3 +j *dim3 +k]
muß heißen
((int*)m)[i * dim2 *dim3 +j *dim3 +k]
Ansonsten ist nix quatsch.
Der Pointer in der Funktionsdeklaration zeigt auf ein 3D-Array, welches
ihr einfach als Parameter übergeben werden kann. Dieser wird in einen
Int-Pointer gecastet, um direkt auf das Element zugreifen zu können. Wer
sich mal etwas näher mit Compiler und deren Arbeitsweise
auseinandergesetzt hat, der weiss wie sie es machen. Sie speichern
Arrays, auch mehrdimensionale, immer linear ab.
sagte ich das nicht bereits mit dem linearen Abspeichern?
Habe auch noch keinen mehrdimensionalen Speicher gesehen.
aber nichtsdestotrotz dass Du die Problematik mit den Pointern begriffen
hast, gibt es sicherlich andere, die mit Pointern noch Probs. haben die
mit Deinem geposteten Text recht wenig anfangen können.
ausserdem lernte ich dass ***zeiger bäbä sind.
So. Aber LtData hat seine Frage ja beantwortet bekommen wie er
mitteilte. Und da brauchen wir uns hier doch nicht zu streiten.
Daher: Happy Coding! Und schon mal Danke an alle die mir weitergeholfen
haben/werden :-)))
Sorry,
war ein schlechter Tag für mich. Ich gehöre zu den armen Schweinen, die
sich immer ihre eigenen Fragen beantworten müssen. Kein weiterer
Softwärkerkollege weit und breit in Sicht. Und das schon seit
Berufsbeginn 1997.
Entschuldigung
Oliver
Ist doch nicht tragisch. Habe inzwischen auch nochmal
nachgesehen. Ein
int foo[3][5][7];
ist bei der Parameterübergabe in eine Funktion kompatibel mit
dem Zeiger
int (*foo)[5][7]