Forum: Mikrocontroller und Digitale Elektronik Pointer auf dreidimensionales Array?


von Sebastian W. (sebastian_w27)


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 :)

von Rene (Gast)


Lesenswert?

[c]
uint8_t ***mein_pointer = mein_array;
[/c|

von Rene (Gast)


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.

von Peter II (Gast)


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.

von Sebastian W. (sebastian_w27)


Lesenswert?

Sieht leider so aus wie Peter schon sagt. Das klappt nicht.

Kann ja auch eigentlich nicht. Denn bei der erstellung des oder der 
Pointer muss doch die größe der Dimensionen des Arrays mit einfließen. 
Denke ich...

von Peter II (Gast)


Lesenswert?

mache normales Array und greife selber darauf zu, was anders würde der 
compiler auch nicht machen.

uint8_t x[SIZE_X*SIZE_Y*SIZE_Z];

wert = x[z*SIZE_Y*SIZE_X + y*SIZE_X + x];

von flipsi (Gast)


Lesenswert?

Sebastian W. schrieb:
> Aber das gibt mir:
>
> initialization from incompatible pointer type
>
> Wo liegt der denkfehler? Oder gibt es eine bessere/andere möglichkeit
> das zu machen?
1
uint8_t mein_array[6][5][2];
2
3
uint8_t  (*mein_pointer)[5][2] = mein_array;

Viele Grüße
  flipsi

von Sebastian W. (sebastian_w27)


Lesenswert?

Danke Flipsi.

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?
1
Wenn:
2
3
mein_array[x][y][z]
4
5
Dann: (?)
6
7
mein_pointer[z][x][y] ?

Danke

von Michael S. (msb)


Lesenswert?

was hälst Du von:

uint8_t        mein_array_t[6][5][2];
mein_array_t  *mein_pointer;

von flipsi (Gast)


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!

von flipsi (Gast)


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

von Arc N. (arc)


Lesenswert?

Sebastian W. schrieb:
> Danke Flipsi.
>
> 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?
>
1
  uint8_t array[6][5][4];
2
  uint8_t (*arrayP)[5][4];
3
  
4
  array[1][2][3] = 5;
5
6
  arrayP = array;
7
  arrayP[1][2][3] = 4;

von Michael S. (msb)


Lesenswert?

sorry, hatte vorhin das typedef vergessen:

typedef uint8_t    mein_array_t[6][5][2];
mein_array_t      *mein_pointer;

von Ein Programmierer (Gast)


Lesenswert?

Also Leute, so langsam werden eure Tips peinlich....

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

mein_array[5][4] = buf[1];

von Michael S. (msb)


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]);

von Sebastian W. (sebastian_w27)


Lesenswert?

Ich danke euch für die guten Ideen und Ratschläge. Ich werde sie die 
Tage mal ausprobieren und schauen was für mich am besten klappt.


Danke & Liebe Grüße

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
Noch kein Account? Hier anmelden.