Pointer auf dreidimensionales Array?

OP #3143524
Lesenswert?

Hallo zusammen :)

Leider konnten mir weder Google, noch die Suche im Forum, eine 
zufriedenstellende Lösung liefern. Deswegen möchte ich hier einfach mal 
kurz meine Frage loswerden. Vielleicht weiß jemand von euch weiter.

Ich möchte in meinem aktuellen AVR Projekt gerne Daten in einem 
dreidimensionalen Array gepuffert zwischen dem Hauptprogramm und einer 
Interrupt Routine austauschen (mittels Pointer?).
Das ganze soll so funktionieren, dass von dem Array zwei Kopien 
existieren. Das erste Array wird in der Interrupt Routine benutzt, 
während das andere Array im Hauptprogramm mit neuen Daten gefüllt wird. 
Ist das Hauptprogramm damit fertig die Daten zu aktualisieren, tauscht 
es die beiden Pointer aus, die auf die Arrays verweisen. Nun Arbeitet 
die Interrupt Routine mit den neuen Daten, während im Hauptprogramm das 
"alte" Array neu befüllt wird.

Wie das mit eindimensionalen Arrays funktioniert ist mir klar. Das habe 
ich schon des öfteren gemacht. Aber wie kann man das bei 
mehrdimensionalen Arrays machen? Ich habe probiert ein Array aus 
Pointern zu verwenden. Aber da scheitert es schon bei der deklaration. 
Ich habe mir das ungefähr so vorgestellt:
1
uint8_t mein_array[6][5][2];
2

3
uint8_t  (*mein_pointer)[6][5] = mein_array;


Aber das gibt mir:

initialization from incompatible pointer type

Wo liegt der denkfehler? Oder gibt es eine bessere/andere möglichkeit 
das zu machen?

Vielen Dank :)
Gast #3143556
Lesenswert?

1
uint8_t ***mein_pointer = mein_array;

Zu früh abgeschickt.

Also: Im Grunde ist das nichts anderes wie ein drei Fachpointer. Erste 
Dimension (***), zweite (**) und dritte (*).

Das sollte so eigentlich klappen.

Grüsse,
R.
Gast #3143563
Lesenswert?

Rene schrieb:
> Also: Im Grunde ist das nichts anderes wie ein drei Fachpointer. Erste
> Dimension (***), zweite (**) und dritte (*).
> Das sollte so eigentlich klappen.

nein sollte nicht. Weil ein

uint8_t mein_array[6][5][2];


ebend keine verschachtelten Pointer sind. Das mapt der Compiler auf ein 
normales Array.
Gast #3143690
Lesenswert?

Sebastian W. schrieb:
> Also die Deklaration klappt so schonmal ohne fehler. Allerdings habe ich
> beim auslesen der Werte nun ein Problem. Wie komme ich über den Pointer
> nun an die einzelnen Werte des Arrays?

Hallo Sebastian!
Anbei mal ein komplettes Beispiel:
1
int bla[3][4][5]; // nicht-lokale Variable wird mit 0 initialisiert
2

3
...
4
int (*foo)[4][5] = &bla[0]; // Oder &bla[1] für die nächste Bank ...
5
 
6
        (*foo)[1][2] = 23; // Zugriff auf Arrayelement
Mein Beispiel war komplett, wurde aber von der Eingabemaske leider als 
vermutlicher Spam erkannt!? So schlecht war der Code ja nun aber nicht!

Bei der Zuweisung von bla and foo schreibt man wohl besser zur 
Verdeutlichung &bla[0], also Adresse von Arrayplatz [0] von bla, auch 
wenn das zu bla identisch ist. Denn schon für bla[1] ist es das nicht 
mehr. Es gibt hier drei Bänke (erster Index) mit 4 x 5 Plätzen.

Zugriff erfolgt dann durch Dereferenzierung von foo und einem 
entsprechenden Arrayzugriff (bitte NICHT über foo[0][x][y], das ist zwar 
erlaubt, aber verwirrt den Leser]. Deine originale Indexierung oben 
hatte allerdings die "Banknummer" hinten, während hier die "Banknummer" 
vorn steht.
Je nach Anwendungsfall kann natürlich auch ein Zeiger auf eine Struktur 
vorteilhafter (weil lesbarer) sein, wie Michael S. es vorschlug, als so 
ein Arraykonstrukt. Nicht so gut ist allerdings die Form, alles in ein 
eindimensionales Array zu stopfen, denn da macht man leider schnell 
Fehler.
C ist eine sehr schöne Sprache; wenn man sie richtig anwendet (mit gnu 
extensions), kann man Quelltexte schreiben, die Gedichten ähneln (z.B. 
Teile des Kernels)!

Weiterhin viel Erfolg
  flipsi

PS: Meine Aussagen erheben keinen Anspruch auf Wahrheit, denn ich bin 
leider (noch) kein C Language-Lawyer; die findest Du in einschlägigen 
newsgroups!
Gast #3143722
Lesenswert?

Noch ein kleiner Nachtrag, die Eingabemaskenspamerkennung hatte mich 
etwas irritiert:
1) Sorry, Michael S. beschreibt KEIN struct.
2) Der Beispielcode verwendet einen Zeiger (foo) auf einen 2D Subteil 
des 3D Array bla. Deine obige Dereferenzierung mit "mein_pointer" ist 
selbstverständlich syntaktisch korrekt
(ich kann sie hier nicht wiederholen, sonst wird wieder Spam erkannt 
.....),
wenn Du foo als einen Zeiger auf ein 3D Array verwenden möchtest. In 
Deinem Falle ist aber vermutlich ein Zeiger auf einen der 2D Teile 
(Registerbank) geeigneter (macht den Code lesbarer), der entsprechend 
getauscht wird (wie im Beispielcode von mir mittels &bla[x]...). Die 
Definition (hier die von foo) ist in C identisch (ob ein Zeiger auf nur 
ein "Objekt" oder auf den Anfang eines 1D Arrays von "Objekten" zeigen 
kann, wird nicht unterschieden).

Viele Grüße
  flipsi
#3144479
Lesenswert?

Bevor der, der sich "Ein Programierer" nennt hier die Leute anmacht, 
sollte er erst mal C lernen!

hier ist mein Beispiel etwas weiter komplettiert:

typedef uint8_t    mein_array_t[6][5][2];
mein_array_t       mein_array[2];
mein_array_t      *mein_pointer = &mein_array[0];

// pointer umschalten in der Interrupt routine
mein_pointer = (mein_pointer==&mein_array[0]) ?
                  &mein_array[1]) : &mein_array[0]);

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren