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.
Ho! Beispiel: void test(int m[3][3]) { m[1][0] = 10; } void main(void) { int a[3][3]; //Drei Zeilen, drei Spalten test(a); } Versuch das mal.
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
@Oliver was hat denn Dein Sourcecode mit Pointern zu tun ? ;-) gruß Axel
Daß die Funktion test() einen solchen übergeben bekommt, auch wenn das auf den ersten Blick gar nicht so aussieht. ;-)
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
Bindung zwischen Pointer und Array´s. .............hatte ich ganz vergessen und das ;-) Gruß Axel auch noch.
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.
@LtData Mal ein Sourcecode von mir zum Thema Pointer und array´s _____________________________________________ #include <stdio.h> #define ROWS 3 /* Zeilenzahl */ #define COLS 4 /* Spaltenzahl */ void main(void) { /* 2D Array mit Initialisierung, 2D Array wird zeilenweise ohne Luecken abgespeichert: m[0][0] m[0][1] ... m[0][3] m[1][0] m[1][1]...m[1][3]...m[2][3] |----- Zeile 0 ------------|------- Zeile 1 ---------|-- ..... Dadurch kann man sich die 3*4 Matrix in einem 1D Array mit 3*4=12 Elementen gespeichert vorstellen vorstellen: Index der Matrix |Index des aequivalienten Vektors i j | k=i*COLS+j -----------------|-------------------------------- 0 0 | 0 0 1 | 1 0 2 | 2 0 3 | 3 1 0 | 4 1 1 | 5 1 2 | 6 ... | ... 2 2 | 10 2 3 | 11 */ float m[ROWS][COLS] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2}; float *fpt=NULL; /* Pointer auf float, geerdet */ int i,j; printf("Zugriff ueber Pointer, der das 2D Feld durchwandert\n"); fpt=&m[0][0]; /* Pointer auf Element 0,0 setzen */ for(i=0; i<ROWS*COLS; i++) /* alle Feldelemente ... */ { printf("%4.1f ", *fpt++); /* Wert ausgeben und danach Pointer */ } /* ein Element weiter setzen */ printf("\n\nZugriff mit Pointer und zwei Indizes\n"); fpt=&m[0][0]; /* Pointer auf das Element 0,0 setzen */ for(i=0; i<ROWS; i++) /* Zeilen... */ { for(j=0; j<COLS; j++) /* Spalten ... */ { printf("%4.1f ",*(fpt+i*COLS+j)); } putchar('\n'); /* neue Zeile */ } printf("\nZugriff ueber Feldname und 2 Indizes\n"); for(i=0; i<ROWS; i++) /* Zeilen... */ { for(j=0; j<COLS; j++) /* Spalten ... */ { printf("%4.1f ",m[i][j]); } putchar('\n'); /* neue Zeile */ } }
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]
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.