Hallo, kann ich auf ein Array statt mit Array[m][n] auch so darauf zugreifen: *(*(array+m)+n)? Also ich meine, ist die dereferenzierung ao korrekt? danke
Wenn du den den Array-Zugriff noch unleserlicher machen möchtest, kannst du auch n[m[array]] schreiben ;-)
Du derefenzierst 2x, nimmst also den Inhalt einer Speicherzelle als Adresse. Das würde funktionieren, wenn du ein Feld von Pointern/Referenzen hast. Bei einem zweidimensionalen Feld ist das wohl kaum das, was du willst. Schon einen Schritt näher wäre *((array+m)+n). Jetzt hast du das nächste Problem: Du hast ein Feld von Feldern. Bei m soll also m*(Feldgröße der 2.Dimension)*(Speichergöße der einzelnen Elemente) addiert werden. Bei n aber nur n*(Speichergöße der einzelnen Elemente). Das müßte mit dem richtigen casten auf ein Feld von Feldern bzw. ein Feld von Elementen gehen. (Wann du wo und wie casten mußt damit das ganze funktioniert, das entnimmst du dem C-Standard oder du castest im Zweifelsfall immer. Und das dann bitte richtig. ;-p ) Bonusaufgabe: array wurde als Referenz einer Funktion übergeben. Der Compiler hat dort keine Ahnung, wie das Feld organisiert ist sondern sieht nur ein eindimensionales Feld unbekannter Größe. Was machst du dort, außer dich aufzuhängen? Ich hoffe, du versuchst nur, C besser zu verstehen und willst ein derartiges Konstrukt nicht ernsthaft einsetzen.
horst schrieb: > Jetzt hast du das nächste Problem: > Du hast ein Feld von Feldern. Bei m soll also m*(Feldgröße der > 2.Dimension)*(Speichergöße der einzelnen Elemente) addiert werden. Bei n > aber nur n*(Speichergöße der einzelnen Elemente). Das müßte mit dem > richtigen casten auf ein Feld von Feldern bzw. ein Feld von Elementen > gehen. (Wann du wo und wie casten mußt damit das ganze funktioniert, das > entnimmst du dem C-Standard oder du castest im Zweifelsfall immer. Und > das dann bitte richtig. ;-p ) Und um das nicht ganz so kompliziert zu machen, wie du es beschrieben hast, gibt es die Schreibweise *(*(array+m)+n). Das funktioniert sehr wohl auch bei Array von Arrays, nicht nur bei Pointer-Arrays. :)
Yalu X. schrieb: > Und um das nicht ganz so kompliziert zu machen, wie du es beschrieben > hast, gibt es die Schreibweise *(*(array+m)+n). Das funktioniert sehr > wohl auch bei Array von Arrays, nicht nur bei Pointer-Arrays. > :) Dann sind wir aber wieder bei einer Zwischenfrage von weiter oben: Wie genau ist array definiert? Denn bei char array[5][4]; ist *(*(array+m)+n) ein Syntaxfehler: 'Dereferencing a non pointer entity'. Oder auch 'Derferencation makes pointer from integer without a cast'. Je nach Compiler. *(array + m*sizeof(*array) + n) wäre korrekt. Anstelle des sizeof könnte man auch einfach 5 schreiben. Denn das 'Problem' besteht darin, dass je nach exakter Variablebdefinition, die simple Schreibweise i = array[m][n]; in mehrere grundverschiedene Operationen umgewandelt werden muss, je nachdem ob man es mit einem char array[5][4]; oder einem char* array[5]; oder gar einem char ** array; zu tun hat, trotzdem aber in allen Fällen identische Array-Syntax benutzen kann.
Karl Heinz Buchegger schrieb: > *(array + m*sizeof(*array) + n) > > wäre korrekt. Anstelle des sizeof könnte man auch einfach 5 schreiben. Das sizeof(*array) würde 1 liefern, da *array vom Typ char ist. Also besser 5 schreiben :)
AND schrieb: > Karl Heinz Buchegger schrieb: >> *(array + m*sizeof(*array) + n) >> >> wäre korrekt. Anstelle des sizeof könnte man auch einfach 5 schreiben. > > Das sizeof(*array) würde 1 liefern, da *array vom Typ char ist. Also > besser 5 schreiben :) No. Bei char array[5][4] ist *array vom Typ char[5]; Wenn du ein 2D Array einmal 'dereferenzierst', landest du bei einem 1D Array.
*(array + m*sizeof(*array) + n) verstehe ich nicht ganz wenn ich z.b. das mache: char array[][5] = {"Das","Ist","Ein","Test"}; dann kann ich sowohl mit array[m][n] als auch mit *(*(array+m)+n) fehlerfrei drauf zu greifen. Ich hatte dazu auch mal ne Frage, und ich glaube du hattest mir auch eine ähnliche Antwort gegeben. Kannst du das erklären? Ich habe es bei mir so nicht zum laufen gebracht. *(*(array+m)+n) Das hier erkläre ich mir so: Mit dem anlegen des arrays, lege ich ja nacheinander die Zeichen in den Speicher. Also Das\0xxIst\0xEin\0xTest\0 wobei x ja zufällig ist, habe ich ja nicht festgelegt. Wenn ich jetzt *(array+m) mache, habe ich doch meinen Pointer auf das erste Zeichen jeweils, also D, I, E, T wenn ich den Pointer dereferenziere und evtl. davor noch vergrößere, also *(*(array+m)+n) , dann habe ich doch mein Zeichen wieder? Oder verstehe ich da was falsch? Ich habe es ausgiebig so getestet und die Adressen geprüft, und die waren alle gleich? Danke
Hab das mal als C Programm gefasst:
1 | #include <stdio.h> |
2 | |
3 | int main(void) |
4 | {
|
5 | |
6 | int i,j; |
7 | char array[][5] = {"Das","Ist","Ein","Test"}; |
8 | |
9 | for(i=0;i<4;i++) |
10 | {
|
11 | for(j=0;j<5;j++) |
12 | {
|
13 | printf("%c",array[i][j]); |
14 | }
|
15 | |
16 | }
|
17 | |
18 | printf("\n"); |
19 | //Das gleiche mit der Pointerversion
|
20 | for(i=0;i<4;i++) |
21 | {
|
22 | for(j=0;j<5;j++) |
23 | {
|
24 | printf("%c",*(*(array+i)+j)); |
25 | }
|
26 | |
27 | }
|
28 | |
29 | //Liefert exact die gleiche Ausgabe
|
30 | |
31 | //Adressen vergleichen
|
32 | printf("\n"); |
33 | for(i=0;i<4;i++) |
34 | {
|
35 | for(j=0;j<5;j++) |
36 | {
|
37 | printf("%p,%p\n",(*(array+i)+j),&array[i][j]); |
38 | }
|
39 | |
40 | }
|
41 | |
42 | return 0; |
43 | }
|
Als Ausgabe erhalte ich das was ich gesagt habe:
1 | Das Ist Ein Test |
2 | Das Ist Ein Test |
3 | 0022FEF4,0022FEF4 |
4 | 0022FEF5,0022FEF5 |
5 | 0022FEF6,0022FEF6 |
6 | 0022FEF7,0022FEF7 |
7 | 0022FEF8,0022FEF8 |
8 | 0022FEF9,0022FEF9 |
9 | 0022FEFA,0022FEFA |
10 | 0022FEFB,0022FEFB |
11 | 0022FEFC,0022FEFC |
12 | 0022FEFD,0022FEFD |
13 | 0022FEFE,0022FEFE |
14 | 0022FEFF,0022FEFF |
15 | 0022FF00,0022FF00 |
16 | 0022FF01,0022FF01 |
17 | 0022FF02,0022FF02 |
18 | 0022FF03,0022FF03 |
19 | 0022FF04,0022FF04 |
20 | 0022FF05,0022FF05 |
21 | 0022FF06,0022FF06 |
22 | 0022FF07,0022FF07 |
Der erste Pointer wird jeweils um 5 Inkrementiert, da das so mit dem Anlegen des Arrays wohl festgelegt wurde. *(array + i*sizeof(*array) + j) Liefert mir irgendwie einen Blödsinn.
SO habe jetzt die Lösung zu dem Problem, und dazu, warum Karl Heinz seine Ansatz nicht stimmt (nicht böse gemeint ;) ) char array[][5] = {"Das","Ist","Ein","Test"}; array zeigt auf array[0] und array[0] zeigt auf array[0][0] a ist damit also ein Zeiger der auf ein char Feld der Länge 5 Zeigt Damit ist ein sizeof garnicht nötig, der Pointer weiß selber wieviele Adressen er weiterspringen muss.
Mike Mike schrieb: > char array[][5] = {"Das","Ist","Ein","Test"}; So erhältst du ein Feld mit Referenzen auf die Strings. Da ist die doppelte Dereferenzierung auch richtig. Probiere es mal mit char array[4][5] = {'D','a','s',0,0,'I','s','t',0,0,'E','i','n',0,0,'T','e','s','t',0}; Ich habe ja nichts dagegen, dass man auch mal gefinkelte Konstrukte verwendet. Aber als Mindestanforderung empfehle ich, dass man selbst wenigstens weiß, was man da tut, und nicht nur, dass es halt zufällig funktioniert.
So funktioniert es für mich ebenfalls, und es geht nicht darum das es zufällig funktioniert (Danke übrigends für den Tipp, dass alles mit Binären Nullen gefüllt wird), sondern ich hatte im Hinterkopf, dass es so geht. Nur musste ich erst gucken wo das auch steht. ISO/IEC 9899:TC3, WG14/N1256, Committee Draft — Septermber 7, 2007): "An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Array types are characterized by their element type and by the number of elements in the array."
Mike Mike schrieb: > *(*(array+m)+n) Du hast recht. Da hab ich mich ins Boxhorn jagen lassen. Wenn man es sich anhand der Datentypen überlegt, kommt raus, das man tatsächlich eine doppelte Dereferenzierung braucht. array char[][] array + m char[][] *(array + m) char[] *(array + m) + n char[] *(*(array + m) + n) char > Wenn ich jetzt *(array+m) mache, habe ich doch meinen Pointer auf das > erste Zeichen Genau genommen hast du einen Pointer auf den Anfang des Strings. Der Datentyp nach dieser Dereferenzierung ist immer noch char[], also ein Arraytyp.
Passiert halt mal ;) Aber so wie du es vorher geschrieben hast, wäre es wenn man die Adresse selber berechnen möchte (also ohne Pointer Arithmetik)
mikeii schrieb: > Passiert halt mal ;) Aber so wie du es vorher geschrieben hast, wäre es > wenn man die Adresse selber berechnen möchte (also ohne Pointer > Arithmetik) Schon mit Pointer Arithmetik. Das lustige ist, dass eine der beiden Dereferenzierungen nur dazu da ist, damit die Datentypen stimmen. Tatsächlich wird dabei aber nichts aus dem Speicher geholt. **(array + m*sizeof(*array) + n) <==> array[m][n]
Karl Heinz Buchegger schrieb: > **(array + m*sizeof(*array) + n) <==> array[m][n] Nein, das stimmt wieder nicht ;-) Die Multiplikation mit m macht die Pointerarithmetik automatisch. Ich habe mal die diskutierten Array-Zugriffsmethoden zusammengestellt und noch eine hinzugefügt:
1 | #include <stdio.h> |
2 | |
3 | unsigned char array[15][4] = { |
4 | { 11, 12, 13, 14 }, |
5 | { 21, 22, 23, 24 }, |
6 | { 31, 32, 33, 34 }, |
7 | { 41, 42, 43, 44 }, |
8 | { 51, 52, 53, 54 }, |
9 | { 61, 62, 63, 64 }, |
10 | { 71, 72, 73, 74 }, |
11 | { 81, 82, 83, 84 }, |
12 | { 91, 92, 93, 94 }, |
13 | { 101, 102, 103, 104 }, |
14 | { 111, 112, 113, 114 }, |
15 | { 121, 122, 123, 124 }, |
16 | { 131, 132, 133, 134 }, |
17 | { 141, 142, 143, 144 }, |
18 | { 151, 152, 153, 154 } |
19 | };
|
20 | |
21 | int main(void) { |
22 | int m=3, n=2; |
23 | unsigned char c; |
24 | |
25 | c = array[m][n]; // 43, richtig |
26 | printf("%d\n", (int)c); |
27 | |
28 | c = *(*(array+m)+n); // 43, richtig |
29 | printf("%d\n", (int)c); |
30 | |
31 | c = **(array + m*sizeof(*array) + n); // 151, falsch |
32 | printf("%d\n", (int)c); |
33 | |
34 | c = *((char *)array + m*sizeof(*array) + n); // 43, richtig |
35 | printf("%d\n", (int)c); |
36 | return 0; |
37 | }
|
Yalu X. schrieb: > Karl Heinz Buchegger schrieb: >> **(array + m*sizeof(*array) + n) <==> array[m][n] > > Nein, das stimmt wieder nicht ;-) > > Die Multiplikation mit m macht die Pointerarithmetik automatisch. Ich sollte mich zur Ruhe setzen :-)
Der Ausdruck
1 | **(array + m*sizeof(*array) + n) |
entspräche übrigens
1 | array[m*sizeof(*array) + n][0] |
Karl Heinz Buchegger schrieb: > Ich sollte mich zur Ruhe setzen :-) Nein, nein, auf keinen Fall =8-o Nur vielleicht heute mal etwas früher ins Bett gehen :)
Sizeof brauchst du z.b. wenn du Speicher allokierts, da gehts nicht automatisch. Hab mal meinen ganzen C Kram nachgeholt, und hab da eigentlich nix mit sizeof gefunden, auser eben Allokation betreffend.
Das ist mal ein super Beispiel für den Unterschied zwischen Arrays und Pointern.
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.