Forum: Compiler & IDEs C-Struktur: Reihenfolge im Speicher festlegen


von Jochen (Gast)


Lesenswert?

Hallo!

Wenn ich eine Struktur anlege, die z.B. so aussieht:
1
typedef struct DataBlock_Struct
2
{
3
  unsigned char destination;
4
  unsigned char source;
5
  unsigned char length;
6
  unsigned char data[20];
7
  unsigned char crc;
8
} DataBlock, *DataBlock_p;
9
10
DataBlock dataToSend;

Was muss ich tun, dass die Reihenfolge der Variablen innerhalb der 
Struktur auch der im Speicher ist, dass ich diese quasi serialisiert 
senden kann (send(&dataToSend[0])?
Wenn die Firmware des Senders die gleiche ist, wie die des Empfängers 
ist, ist die Wahrscheinlichkeit hoch, dass es passt.
Bei Unterschiedlichen gibt es doch keine Gewähr. Oder gibt es hier einen 
Trick?

Gruß
Jochen

von Peter II (Gast)


Lesenswert?

Jochen schrieb:
> Bei Unterschiedlichen gibt es doch keine Gewähr. Oder gibt es hier einen
> Trick?

ja gibt es - verzichte auf die stuct. Sende die Daten einzeln dann 
stimmt es immer.

Wenn du unbedigt die stuct verwenden willst, solltest du in der doku von 
deinem compieler lesen wie du sie "packt" ablegen kannst.

von Klaus W. (mfgkw)


Lesenswert?

Von welcher Firmware redest du?

Die Reihenfolge ist m.W. nicht prinzipiell garantiert und kann (zusammen 
mit evtl. eingefügten Füllbytes) vom Compiler, dessen Version und ggf. 
Compileroptionen abhängen.

Wenn man eine Reihenfolge wasserdicht erzwingen will, sind also structs 
fehl am Platz; eine alternative wäre ein uint8_t-Array, auf das man mit 
unions oder Zeigermimik die eigentlichen Werte drüberlegt. Naja.

Allerdings kenne ich keinen C-Compiler, der die Elemente einer struct in 
einer anderen Reihenfolge als der angegebenen ablegt.
Insofern würde ich vermutlich einfach die Reihenfolge als gegeben 
hinnehmen.

von Jochen (Gast)


Lesenswert?

Peter II schrieb:
> ja gibt es - verzichte auf die stuct. Sende die Daten einzeln dann
> stimmt es immer.

Dann habe ich aber kleine, aber dennoch messbare und unerwünschte 
Sendepausen, wenn ich einen "Kontextwechsel" durchführen muss.

Bei einem Byte-Stream, kann ich einfach "durchsenden".

Klaus Wachtler schrieb:
> eine alternative wäre ein uint8_t-Array, auf das man mit
> unions oder Zeigermimik die eigentlichen Werte drüberlegt.

Sind Unions!? Da fängt doch alles bei der gleichen Adresse an und die 
größte Variable bestimmt die Größe der Union ... !?

von Peter II (Gast)


Lesenswert?

Jochen schrieb:
> Dann habe ich aber kleine, aber dennoch messbare und unerwünschte
> Sendepausen, wenn ich einen "Kontextwechsel" durchführen muss.

eigentlich nicht, dann die sendeeinheit hat doch wohl noch einen kleinen 
sendepuffer. Dieser reicht aus um die nächsten daten reinzuschieben.

von Udo S. (urschmitt)


Lesenswert?

Schreibe dir Funktionen die ein gewünschtes Struct in ein Byte Array 
umwandeln und aus einem Byte Array wieder eine solche Struktur erzeugen. 
Gesendet und empfangen wird dann das Byte Array.
So ist es transparent und unabhängig und du brauchst keine 
Sendefunktionen für n verschiedene Daten, sondern nur eine für bytes.

von Jochen (Gast)


Lesenswert?

Udo Schmitt schrieb:
> Schreibe dir Funktionen die ein gewünschtes Struct in ein Byte Array
> umwandeln und aus einem Byte Array wieder eine solche Struktur erzeugen.
> Gesendet und empfangen wird dann das Byte Array.
> So ist es transparent und unabhängig und du brauchst keine
> Sendefunktionen für n verschiedene Daten, sondern nur eine für bytes.

Serialisieren und deserialisieren ...

von Udo S. (urschmitt)


Lesenswert?

Jochen schrieb:
> Serialisieren und deserialisieren ...

Jepp, den Begriff hast du ja schon verwendet:

Jochen schrieb:
> dass ich diese quasi serialisiert senden kann (send(&dataToSend[0])?

Nachtrag. Wenn es portabel sein soll macht es immer Sinn multibyte 
Variablen unabhängig von der Hardware einheitlich zu serialisieren 
(Stichwort net byte ordering)

von Jochen (Gast)


Lesenswert?

Udo Schmitt schrieb:
> Nachtrag. Wenn es portabel sein soll macht es immer Sinn multibyte
> Variablen unabhängig von der Hardware einheitlich zu serialisieren
> (Stichwort net byte ordering)

Ist das diese LSB-, MSB-Thematik!?

von Jochen (Gast)


Lesenswert?

Bzw. Big- Little Endian...

Gibt es dafür Beispielcode?

von Andreas B. (andreas_b77)


Lesenswert?

Klaus Wachtler schrieb:
> Die Reihenfolge ist m.W. nicht prinzipiell garantiert und kann (zusammen
> mit evtl. eingefügten Füllbytes) vom Compiler, dessen Version und ggf.
> Compileroptionen abhängen.

Die Reihenfolge ist garantiert, der Compiler darf nur Füllbytes 
einfügen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andreas B. schrieb:
> Die Reihenfolge ist garantiert, der Compiler darf nur Füllbytes
> einfügen.

Da bei Jochen alle Daten als "unsigned char" deklariert sind,
kommen auch keine Füllbytes in Frage, denn char braucht (unabhängig
von der Bitanzahl, die es belegt) nie zusätzliches Padding.

von Udo S. (urschmitt)


Lesenswert?

Jörg Wunsch schrieb:
> Da bei Jochen alle Daten als "unsigned char" deklariert sind,
> kommen auch keine Füllbytes in Frage, denn char braucht (unabhängig
> von der Bitanzahl, die es belegt) nie zusätzliches Padding.

Ich hatte mir das Struct gar nicht genau angeschaut. Mir gings um die 
prinzipielle Vorgehensweise, weil das immer wieder Thema ist

Wie sieht das bei Array von characters aus. Da ist ein char Array dabei. 
Wird das ggf. auf manchen Maschinen auf durch 2 (4) teilbare Adressen 
gelegt?

von raute (Gast)


Lesenswert?

Jochen schrieb:
> Udo Schmitt schrieb:
>> Nachtrag. Wenn es portabel sein soll macht es immer Sinn multibyte
>> Variablen unabhängig von der Hardware einheitlich zu serialisieren
>> (Stichwort net byte ordering)
>
> Ist das diese LSB-, MSB-Thematik!?
Ja.
Suche einfach nach ntohs, htons bzw. ntohl, htonl. (Falls du es 
überhaupt brauchst.)

Der kleine zottelige Jedi ist auch nicht verkehrt.
http://www.zotteljedi.de/socket-tipps/xtox.html

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Udo Schmitt schrieb:
> Wie sieht das bei Array von characters aus. Da ist ein char Array dabei.
> Wird das ggf. auf manchen Maschinen auf durch 2 (4) teilbare Adressen
> gelegt?

Nö, gibt's keinen Grund dafür.

Vorsicht ist mit so einer struct natürlich auf (exotischen) Maschinen
geboten, bei denen CHAR_BIT != 8 ist.

von Jochen (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Da bei Jochen alle Daten als "unsigned char" deklariert sind,

In diesem Beispiel. Es gibt aber auch Structs mit long- und 
double-Werten

raute schrieb:
> Suche einfach nach ntohs, htons bzw. ntohl, htonl. (Falls du es
> überhaupt brauchst.)

Wollte eigentlich unabhängig von fertigen Bibliotheken sein ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jochen schrieb:

>> Da bei Jochen alle Daten als "unsigned char" deklariert sind,
>
> In diesem Beispiel. Es gibt aber auch Structs mit long- und
> double-Werten

Dann solltest du besser passende Beispiele posten. ;-)

Du bist immer auf der sicheren Seite, wenn du bei verschiedenen
Plattformen jegliches mögliches Padding von vornherein mit in der
Struktur unterbrings bzw. die Struktur passend aufbaust.  Dazu
geht man vom größeren zum kleineren Datentyp vor.  Wenn du also
double-Elemente hast, kommen diese am Anfang, gleichfalls andere
64-bit-Typen.  Danach kommen die 32-bit-Elemente usw. usf.  An
der Grenze zwischen den verschiedenen Größten musst du ggf. dann
die Füllbytes auffüllen, die der Compiler ohnehin auffüllen müsste,
die benennst du dann eben einfach selbst, ohne sie am Ende zu
benutzen.

> raute schrieb:
>> Suche einfach nach ntohs, htons bzw. ntohl, htonl. (Falls du es
>> überhaupt brauchst.)
>
> Wollte eigentlich unabhängig von fertigen Bibliotheken sein ...

Das sind keine Bibliotheken, sondern Makros bzw. Inline-Funktionen,
die man auf der jeweiligen Zielplattform so effizient wie möglich
realisiert.  Manche CPUs haben dafür gleich eigene Befehle parat.

Wenn die Zielmaschine bereits "network byte order" benutzt (also
big endian), sind diese Teile Nullmakros.

von Michael R. (dj_motionx)


Lesenswert?

Hallo !
Wollte nur zusätzlich auch noch folgenden Link zum Thema einwerfen:
http://www.parashift.com/c++-faq-lite/serialization.html

Beste 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.