Hallo achim,
gehe ich dann richtig in der Annahme, dass dabei dann
Strukturen und Datentypen > 1 Byte Tabu sind?
JAIN )
Das wäre natürlich schade, da mir z.B. für die Beschreibung
eines Protokolls eine sinnvolle C-Programmiermöglichkeit
fehlt. Prinzipiell kann ich ja nichtmal einen Pointer auf ein
Int32 in einen Datenstrom legen, da Int32-Pointer je nach
Prozessor 2 oder 4-Byte alligned sein müssen.
Das ist noch das Harmlose, viel schlimmer sind schon Little- oder Big-Endian bei 16Bit Daten …
Wir verwenden daher für jedes Kopieren in und aus einem
Datenstrom quasi memcpy, aber ich hatte gehofft, es geht
irgendwie einfacher, „lesbarer“, ähnlich komfortabel wie mit
Strukturen.
Gerade memcpy() ist TABU !!!
Es wäre schön wenn man einfach eine struct üder die Leitung kopieren könnte.
Gerade bei Compilern für Intel-CPUs kann man das Allignement einstellen. Dadurch kann ich den gleichen Source mit einem Compiler zweimal übersetzen und diese beiden, scheinbar identischen, Programme können nicht mehr miteinander kommunizieren.
Man kann soetwas mit „#if sizeof()“ konstrukten absichern, zumindest soweit, dass der Compiler Fehlermeldungen macht, wenn die Einstellungen nicht stimmen.
Weiterhin kann man die structs so erstellen, dass man selber char z.B. auf Modulo 2 oder 4 auffüllt. Aber das geht auch nur innerhalb bestimmter Grenzen. Allerdings musst du dazu verstanden haben was der Compiler und der Linker eigentlich genau wie machen …
Das Einzige was fast immer funktioniert ist alles byteweise zu zerlegen und auf der Gegenseite wieder zusammen zusetzen.
Im weiteren Text steht „Compiler“ einerseits für unterschiedliche Versionen von unterschiedlichen Herstellern, sowie für Compiler für unterschiedliche CPUs.
Also nehmen wir den Wert 0x1234 welche in einem int abgelegt wird.
Je nach Compiler ist ein int 16, 32, 64 oder sonstwas Bits lang !
Nehmen wird mal 16Bit an.
union
{
char c[2];
int i;
} x\_int
x\_int.i = 0x1234;
Bei Little-Endian ist nun
x_int.c[0] == 0x12 und
x_int.c[1] == 0x34
Bei Big-Endian ist es aber
x_int.c[0] == 0x34 und
x_int.c[1] == 0x12
Du musst also zuerst einmal festlegen wie die Daten byteweise übertragen werden sollen!
Ich lege jetzt mal fest, dass unser Wert 0x1234 als
0x12 gefolgt von 0x34
über die Leitung gehen soll.
int i = 0x1234;
SENDEN:
send\_byte( (i \>\> 16) & 0xFF );
send\_byte( i & 0xFF );
EMPFANGEN:
i = (get\_byte()
Die Maskierung mit 0xFF, 0xFF00 und 0x00FF scheint auf den ersten Blick überflüssig zu sein.
Da aber int nicht 16Bit gross sein muss und zudem auch nicht garantiert ist, dass es signed oder unsigned ist, kann die die Signextension einen grossen Strich durch die Rechnung machen.
MfG Peter(TOO)