C-Struktur: Reihenfolge im Speicher festlegen

Gast #2662976
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
Gast #2662980
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.
#2662981
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.
Gast #2662995
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 ... !?
Gast #2662997
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.
#2662999
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.
Gast #2663002
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 ...
#2663031
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?
Gast #2663035
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
Moderator Persönliche Seite #2666084
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.

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