Forum: Compiler & IDEs struct und Array (Arduino)


von Arduino Anfänger (Gast)


Lesenswert?

Hallo zusammen,

ich spiele gerade ein ein wenig mit UDP herum. Ich empfange per UDP 
nacheinander mehrere Array's zwischen 25-1341 Bytes. Diese möchte ich in 
entsprechende Strukturen ablegen, die auch definiert sind. Nur stehe ich 
auf dem Schlauch, da ich nicht weiß wie ich es umkopieren soll.

memcpy funktioniert ja nicht, da das jeweilige Struct, aus verschiedenen 
Datentypen besteht, wie int16, float etc.

Wie stelle ich das am besten an?

Gruß Anfänger

von A. S. (Gast)


Lesenswert?

Entweder schreibst Du Dir entsprechende Konverter, die jedes Byte 
einzeln bearbeiten, ....

Oder du stellst sicher, dass endianess, allignment und packing gleich 
sind, dann  memcpy oder Struktur-zuweisung.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Siehe den Artikel Serialisierung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Arduino Anfänger schrieb:
> memcpy funktioniert ja nicht, da das jeweilige Struct, aus verschiedenen
> Datentypen besteht, wie int16, float etc.

Wieso sollte es das nicht tun? Natürlich kann man Strukturen per memcpy 
kopieren.

Das geht nur dann nicht, wenn das empfangene Strukturabbild nicht dem 
Deiner Zielstruktur entspricht.

Daß Du Deine Daten zunächst als uint8_t-Array empfängst, hat nichts mit 
der Art des Strukturabbildes zu tun.

von Olaf (Gast)


Lesenswert?

> Nur stehe ich
> auf dem Schlauch, da ich nicht weiß wie ich es umkopieren soll.

Du koenntest das automatisch im Hintergrund vom Compiler machen lassen.
Hier mal ein Beispiel wie ich das mache:

struct HeaderType
{
  uint32_t crc32;         //Prüfsumme des Datenstructes
  uint16_t length;        //Laenge des Datenstructes
  uint8_t  UsedDataType;  //Type des Datenstructes
  uint8_t  Version;       //Version des Datenformates
  uint32_t UpCounter;     //Ein Zaehler den der Sender bei jedem Paket 
um 1 erhoeht
  uint8_t  encoding;      //0= keine Verschluesselung
  uint8_t  unused1;       //fuer zukuenftige Erweiterungen
  uint8_t  unused2;       //fuer zukuenftige Erweiterungen
  uint8_t  crc8;          //Pruefsumme das HeaderTypes
} _attribute_ ((packed));

union HeaderUnion
{
  struct HeaderType Header;
  uint8_t           Byte[16];
};

[..]

  HeaderUnion UDP_Header;

[..]

        //Den Header kopieren
        for(i=0; i<sizeof(HeaderUnion); i++)
          {
                UDP_Header.Byte[i] =    *UDP_Paket++;
          }

[..]

        //Pruefsumme des Header okay?
        if (UDP_Header.Header.crc8 != CRC8(UDP_Header.Byte, 
sizeof(HeaderUnion) -1 ) ) return ( UDP_HEADER_\
CRC);


Das funktioniert, sieht elegant aus, setzt aber voraus das du verstehst 
was du machst weil es abhaengig von Compiler und Wordbreite im 
Controller sein kann. Aber bei der geeigneten Wahl von Pruefsummen von 
Header und Daten faellt man nicht so schnell auf die Nase.

Olaf

von Niklas Gürtler (Gast)


Lesenswert?

Olaf schrieb:
> Das funktioniert

Ist in C aber unportabel und in C++ (Arduino!) ganz verboten (siehe den 
Artikel).

von Olaf (Gast)


Lesenswert?

> Ist in C aber unportabel und in C++ (Arduino!) ganz verboten (siehe den
> Artikel).

Auf die Probleme hab ich hingewiesen.

Lustigerweise ist das ein Codeausschnitt den ich verwende um von meinem 
PC aus (Qt) die Helligkeit meiner Schreibtischlampe (ESP8266/Arduino) 
einzustellen. Es ist also wohl doch nicht ganz verboten und nicht ganz 
unportabel. Und da ich sowohl fuer header wie auf fuer Daten jeweils 
eine Pruefsumme verwende wuerde es mir auffallen sollte es doch 
irgendwann mal ein Problem geben.

p.s: die Methode zur en/dekodierung meiner Daten in/aus einem UDP-Paket 
verwende ich 1:1 kopiert, sowohl in Arduino wie auch im Qt-Programm.

Olaf

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olaf schrieb:
> Es ist also wohl doch nicht ganz verboten und nicht ganz
> unportabel.

Das ist ja die Tücke an Undefined Behaviour (d.h. "verbotenen" Dingen) - 
es kann den Anschein haben zu funktionieren, und wenn du eine 
Kleinigkeit änderst (Compiler, -Version, -Optionen, Plattform, ...) 
klappt es nicht mehr. Das Argument "funktioniert doch" zieht hier also 
nicht. In Serialisierung ist das alles erläutert und begründet, 
inklusive korrekter Lösungen.

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.