Hallo!
Wenn ich eine Struktur anlege, die z.B. so aussieht:
1
typedefstructDataBlock_Struct
2
{
3
unsignedchardestination;
4
unsignedcharsource;
5
unsignedcharlength;
6
unsignedchardata[20];
7
unsignedcharcrc;
8
}DataBlock,*DataBlock_p;
9
10
DataBlockdataToSend;
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
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 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.
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 ... !?
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.
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.
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 ...
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)
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!?
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.
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.
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?
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
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.
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 ...
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.