Zeiger auf array Element in Union
-
Moin,
kurze Hintergrund Info: Ich entwickele schon seit einiger zeit mit Freunden einen Autopiloten für Schiffsmodelle. Die Software wird auf einem Atmega644p laufen und ist in C Programmiert, ich hätte jetzt hier allerdings eine rein Software technische Frage.
Da das gesamte Programm sehr komplex wird, möchte ich es gerne in einzelne Module aufteilen. Da wären Protokoll (mit de- und encodierung), die Routenverwaltung, das Sensormodul (abfrage und Auswertung der Sensoren über einen Timer), und das Steuermodul. Die einzelnen Module werden in Strukturen organisiert, also eine Art OOP (eig. nicht von C unterschützt). Die Objekte übergebe ich an die Funktionen einfach als Parameter.
Ich möchte das ganze so programmieren, dass ich die einzelnen Module jederzeit ändern, oder komplett austauschen kann. Da aber viele Daten von mehreren Modulen gebraucht werden, wäre eine hohe Abhängigkeit bei den verschiedenen Variablen vorhanden.
Um die Abhängigkeit zu vermeiden könnte ich die Daten Zentral speichern. Dann gäbe es mehrere Möglichkeiten: Ich könnte die einzelnen zentralen Variablen als Parameter oder Zeiger übergeben (je nachdem, wie viele Daten gebraucht und geschrieben werden müssen). Oder ich erstelle eine Funktion, die nachdem Variablen verändert wurden, die neuen Daten an alle Module verteilt. Diese beiden Lösungen sind, meiner Meinung nach aber nicht optimal.
Meine optimale Idee ist, finde ich zumindest:
Ich erstelle Zentral ein "char array" mit vielen Elementen.
Dazu kommt noch ein enuem, in das ich schreibe, was in den einzelnen Elementen gespeichert wird.
Wenn ich z.b. ein float habe, dass ich darin speichern möchte, werden die ersten vier Bytes dafür reserviert. Jede weitere Variable bekommt immer die nötigen Elemente im array hinter der letzten gespeicherten Variable.
Vorteil ist z.b. dass ich aus dem enum automatisch die Index Zahlen bekomme.
z.b.enum e {LAT_1,LAT_2_LAT_3_LAT_4,LON_1,LON_2_LON_3,LON_4};
LAT_1 - 4 sind ein Float, und LON_1 -4 sind ebenfalls ein Float.
So könnte ich in dem enum immer etwas ergänzen oder verändern, und die Varialen bkommen automatisch ihre neuen Indexe.Um das in den Modulen anzuwenden:
Für alle Variablen > 1 Byte, erstelle ich Unions.typedef union INT{ int a; char b[2]; }INT; typedef union FLOAT{ float a; char b[4]; }FLOAT;
In den einzelnen Modulen werden für die Daten, die benötigt werden Module angelegt. Um die Daten nun auszutauschen, möchte ich Zeiger der einzelnen zentralen array Elemente in den Unions speichern, dass man automatisch, wenn man
in den/das (kp welcher Artikel) jeweiligen float/int oder char array des unions schreibt, dass man automatisch ich die Elemente des zentralen Arrays schreibt.Meine Frage ist, wie ich die Zeiger der Elemten in das array im Union bekomme, um automatisch in das zentrale Array zu schrieben.
Hier nochmal wie ich mir das vorgestellt habe: (Es werden die Unions und das enum von oben verwendet.)Zentrales Array: char arr[256]; Modul 1: FLOAT lat; FLOAT lon; &lat.b[0] = *arr[LAT_1]; &lat.b[1] = *arr[LAT_2]; &lat.b[2] = *arr[LAT_3]; &lat.b[3] = *arr[LAT_4]; &lon.b[0] = *arr[LON_1]; &lon.b[1] = *arr[LON_2]; &lon.b[2] = *arr[LON_3]; &lon.b[3] = *arr[LON_4];
Ich kenn mich mit Zeigern noch nicht sogut aus.
Ziel ist es sozusgane, die Adressen vom Union zu verändern, dass sie auf die Elemnte mit dem Indexern des Zentralen Arrays zeigen.
Damit ich in jedem Modul auf die Daten zugreifen kann, ohne irgentwelche Daten hinund her zu schieben.Ich hoffe jemand kann mit helfen.
MfG
Philipp
-
Um das in den Modulen anzuwenden:
Für alle Variablen > 1 Byte, erstelle ich Unions.Warum erstellst du unions?
Ich verstehe nicht, worauf du hinaus willst.
Was benötigt jedes deiner Module an Daten?
Soweit ich dein Deutsch interpretieren konnte, entnehme ich, dass du in jedem Modul 2 floats benötigst, und die willst du zentral/global definieren und "flexibel" zugreifen.
Wenn das so ist, brauchst du weder unions noch Zeiger sondern ein zentrales struct Array, das ein Element für jedes vorhandene Modul enthält.also
enum {MODUL1,MODUL2,MODUL3}; typedef struct { float lat,lon; } LatLon; LatLon daten[MODUL3-MODUL1+1]; Modul1.c printf(" %f %f ", daten[MODUL1].lat,daten[MODUL1].lon ); ... Modul2.c printf(" %f %f ", daten[MODUL2].lat,daten[MODUL2].lon ); usw.
-
Wutz schrieb:
Um das in den Modulen anzuwenden:
Für alle Variablen > 1 Byte, erstelle ich Unions.Warum erstellst du unions?
Ich verstehe nicht, worauf du hinaus willst.
Was benötigt jedes deiner Module an Daten?
Soweit ich dein Deutsch interpretieren konnte, entnehme ich, dass du in jedem Modul 2 floats benötigst, und die willst du zentral/global definieren und "flexibel" zugreifen.
Wenn das so ist, brauchst du weder unions noch Zeiger sondern ein zentrales struct Array, das ein Element für jedes vorhandene Modul enthält.also
enum {MODUL1,MODUL2,MODUL3}; typedef struct { float lat,lon; } LatLon; LatLon daten[MODUL3-MODUL1+1]; Modul1.c printf(" %f %f ", daten[MODUL1].lat,daten[MODUL1].lon ); ... Modul2.c printf(" %f %f ", daten[MODUL2].lat,daten[MODUL2].lon ); usw.
Hi,
tut mir leid, wenns unverständlich war.
Die unions brauche ich für das Protocol, weil ich die sprintf Funktion nicht verwenden kann, da die auf Mikrocontrollern kein Float unterstützt und viel zu langsam ist, deswegen speicher ich die Floats und Ints in unions, damit ich für die Kommunikation, einfach die 4 bwz. 2 einzelnen Bytes senden kann, die dann am PC mit einer weiteren Union wieder zum Float/Int gemacht werden.Ich möchte, dass die verschiedenen Module nicht die Daten hin und her schicken müssen, sondern, dass die zentral gespeichert werden.
Dazu möchte ich gerne wissen, wie ich die Adresse eines einzelnen Elementes eines arrays bekomme, und wie ich diese Adresse in dem array in einem Union einsetzte, damit, die Daten, die ich in das Union schreibe, in dem zentralen Array gespeichert werden.
MfG
Philipp
-
Warum sendest und empfaengst du die Daten nicht im Binaerformat?
-
knivil schrieb:
Warum sendest und empfaengst du die Daten nicht im Binaerformat?
Wie genau meinste das?
Ich kann maximal 1 Byte am stück senden, die Floats und Ints muss ich demnach Byte für Byte senden, da die sprintf nicht geht, mach ich das mit der union.
Wie könnte ich es denn noch senden?MfG
Philipp
-
Ich habe keine Ahnung, wie deine Funktion heißt, ich nenne sie einfach mal send_byte.
void send_bytes(void const* data, size_t n) { for(char const* p = data; n--; ++p) send_byte(*p); }
Und dann kann man die Funktion so verwenden:
float f = 3.14f; send_many_bytes(&f, sizeof f);
-
Die Adresse eines Feldelements ermittelt man wie auch in anderen Fällen mit dem Adressoperator &, also
int array[100];
int *i1 = &array[0];
int *i2 = &array[1];
...In einem Array hat jedes Element den gleichen Typ, wenn du hier flexibel sein willst, musst du also auch hier union verwenden und dir jeweils auch noch den Typ "merken":
typedef union {int i;char b[2];} INT_T; typedef union {float f;char b[4];} FLOAT_T; typedef struct {int typ;union {INT_T i;FLOAT_T f;} wert;} ELEMENT; enum {MODUL1,MODUL2,MODUL3}; enum {TYPINT,TYPTFLOAT}; ELEMENT zentral[MODUL3-MODUL1+1]; Modul1.c ELEMENT *e = &zentral[MODUL1]; e->typ=TYPINT; /* Typfestlegung hier notwendig, damit später die Größe richtig ermittelt werden kann */ e->wert.i.i=2; printf("%d",e->wert.i.i); Modul2.c ELEMENT *e = &zentral[MODUL2]; e->typ=TYPFLOAT; e->wert.f.f=123.456; printf("%f",e->wert.f.f);
Für die Übertragung der Bytes greifst du dann auf das wert-Element zu und ermittelst die Größe der zu übertragenden Bytes anhand des typ-Elements, du siehst also, die untergeordnete union brauchst du eigentlich gar nicht bzw. das char-Element brauchst du nicht, du musst nur die Anzahl Bytes zugehörig zu einer wert-Adresse ermitteln können.
for(i=0;i<3;++i) switch( zentral[i].typ ) { case TYPINT: sendbytes( BLAFASEL, &zentral[i].wert, sizeof(int) ); /* wichtig hier, dass du einfach &...wert verwenden kannst */ ... case TYPFLOAT: sendbytes( BLAFASEL, &zentral[i].wert, sizeof(float) ); ...
-
Ok, danke, so wirds funktionieren.
mFg
Philipp