C exact 36 byte verschicken
Hallo,
entschuldigt den kryptischen Betreff.
Mein Problem:
Ich benoetige eine Datenstruktur die 36 bytes nicht ueberschreitet. Gleichzeitig soll diese Struktur als "ein Block" vorliegen.
Erstelle ich ein struct habe ich das Problem, dass all seine Elemente auf die groesste Einheit aufgeblaeht werden. Siehe Beispiel1. Hier hatte ich 10 byte erwartet. Tatsaechlich hat die Struktur aber 16 byte. Finde ich ja auch nachvollziehbar.
Beispiel 1:
struct TTestC
{
char cA[1];
char cB[1];
double testB;
};
Im zweiten Ansaty moechte ich es mit bitfields probieren. Dabei habe ich mir noch keine weiteren Gedanken ueber das bit-jonglieren gemacht (um z.B. einen double in 2 int32 zu speichern). Angeblich wird dabei "quasi" komprimiert. Leider fuehrt Beispiel2 auch nicht zu den erwarteten 10 byte, sondern zu 12 byte. Da zwar cA und cB quasi komprimiert werden, dies aber auch wieder in einen 32bit block, da fA und fB ebenfalls 32bit gross sind.
struct TBitfield2
{
unsigned cA : 8;
unsigned cB : 8;
unsigned fA : 32;
unsigned fB : 32;
} test2;
Wie zaubere ich mir eine Struktur mit exact 10 byte? In dem ich alles auf 8 bit herunterbreche und noch mich auf noch mehr bit-magic einstelle (Beispiel3).
Beispiel 3:
struct TBitfield3
{
char cA : 8;
char cB : 8;
char fA : 8;
char fB : 8;
char fC : 8;
char fD : 8;
char fE : 8;
char fF : 8;
char fG : 8;
char fH : 8;
} test3;
Wobei ich hier auf die bit zuweisung verzichten und nur char verwenden kann, ausser bei meinen 5 bit und 3 bit Feldern.
Da ich meine Loesung gerade weitestgehend selbst erarbeitet habe und nur abschicke damit andere Nutzen ziehen koennen noch eine Frage:
Kann mir jemand gute Internetseiten oder supportnet-artikel empfehlen (aus dem Aermel geschuettelt) die mir die ganze Arbeit mit den bits ueberhaupt erklaeren?
Und natuerlich: Gibt es nicht doch noch einfachere Loesungen? Habe ich etwas uebersehen? Liege ich voellig falsch? Was habe ich nicht mitgeteilt, dass es nun voellig unmoeglich macht nach zu vollziehen was ich ueberhaupt will?
Vielen Dank :)
Antwort schreiben
Antwort 1 von chris_isd vom 14.05.2020, 12:30 Options
Gerade ist mir noch in den Sinn gekommen:
C arbeitet bei den bitfields nicht gerade "automatisch intelligent"
Trotz gleichen Inhalts von Beispiel55 und Beispiel66 hat jedes eine andere Groesse. Als Summe erwarte ich 12 byte fuer beide. Tatsaechlich hat Bsp.55 aber 16 byte und Bsp.66 die 12 byte.
Warum? Mir fehlt gerade die Kraft das zu erklaeren. ;)
Jedenfalls werden in Bsp.55 32bit bloecke verwendet. cA in einen 32er, cB anschliessend in den selben 32er. fA passt nicht mehr in den 32 mit rein. Der 32er wird aufgefuellt und anschliessend der neue 32er block fuer fA geschrieben, dann fB und ein 32er fuer iA. Sortiert man cA, cB und iA zusammen bekommt man fortlaufend einen 32bit block gefuellt. Bravo!
Beispiel55:
struct TBitfield55
{
char cA : 8;
char cB : 8;
int fA : 32;
int fB : 32;
short int iA : 16;
} test55;
Beispiel66:
struct TBitfield66
{
char cA : 8;
char cB : 8;
short int iA : 16;
int fA : 32;
int fB : 32;
} test66;
Antwort 2 von chris_isd vom 14.05.2020, 12:42 Options
Nach weiterer ueberlegung werde ich aber wohl doch auf einen buffer aus 36 byte aus je 8 bit zurueckgreifen und die bits direkt manipulieren, so dass ich diese 36 byte in der gewuenschten order uebers netzwerk schicke. Ich kann ja leider nicht die informationen sortieren wie es mir passt.
Antwort 3 von Supermax vom 14.05.2020, 16:57 Options
Um auf Prozessoren mit 32 oder 64 bit Datenwortbreite die bestmögliche Speicherperformance zu erzielen, werden Datentypen, die an sich mit weniger Bits auskommen, vom Compiler häufig auf ganze 32- bzw. 64-bit Grenzen (entspricht durch 4 bzw. 8 teilbaren Speicheradressen) verschoben. Auf diese Weise werden aus den 1 + 1 + 8 bytes aus deinem ersten Beispiel eben 4 +4 + 8 Bytes, wobei von den 4 bytes eben nur ein byte für den "char" Datentyp verwendet werden.
Dieses "alignment" läßt sich unter Umständen über Compiler-Optionen oder Präprozessor-Direktiven global oder nur für bestimmte Strukturen deaktivieren bzw. steuern.