C-Struktur: Reihenfolge im Speicher festlegen

Gast #2662976
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
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
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
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
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
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
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
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
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
Gast #2665994
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 ...
Moderator Persönliche Seite #2666084
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

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.