sizeof () Teil einer C struct - Sorte von

8

Ich möchte einen Teil der Daten in einigen C-Structs finden, um sie teilweise zu serialisieren / deserialisieren, indem ich die Bytes vom Speicher auf die Festplatte schreibe und umgekehrt.

Die Strukturen sind nicht im Voraus bekannt, sie sind dynamisch mit meinem eigenen C-Code-Generator (sowie dem Code, der es serialisieren wird) gebaut. Die serialisierbaren Felder werden am Anfang der Struktur platziert.

Nehmen wir an, wir haben eine Struktur mit 4 Feldern, und die ersten beiden müssen serialisiert werden:

%Vor%

Ich habe vor, den Zeiger auf die Strukturvariable zu nehmen und die n Bytes zu schreiben / zu lesen, die diese beiden ersten Felder ( x1, x2 ) abdecken. Ich denke nicht, dass ich mich um die Ausrichtung / das Packen kümmern muss, weil ich nicht beabsichtige, dass die Serialisierung verschiedene Kompilationen überlebt (nur eine einzigartige ausführbare Datei wird erwartet, dass sie die Daten liest / schreibt). Und da ich mich auf eine breite Palette von Compilerarchitekturen konzentriere, möchte ich keine Annahmen zu Alignment-Packing- oder Compiler-spezifischen Tricks machen.

Dann muss ich Bytes zählen. Und ich kann nicht einfach sizeof(st.x1)+sizeof(st.x2) wegen Alingment-Padding machen. Also, ich plane Zeiger vom Beginn der Struktur bis zum ersten "nicht persistenten" Feld subtrahieren:

%Vor%

Das scheint zu funktionieren. Und es kann in einem Makro platziert werden.

(Für den Datensatz: Ich habe auch versucht, ein anderes Makro zu schreiben, das keine Instanz der Struktur benötigt, so etwas wie das , aber das scheint hier nicht möglich - aber das macht mir nichts aus.

Meine Frage: Ist das korrekt und sicher? Kannst du eine potenzielle Fallstricke oder einen besseren Ansatz sehen?

Unter anderem: Nehmen C-Standard (und De-facto-Compiler) an, dass die Strukturfelder im Speicher in der Reihenfolge liegen, in der sie in source definiert sind? Das ist wahrscheinlich eine dumme Frage, aber ich möchte sicher sein ...

UPDATE: Einige Schlussfolgerungen aus den Antworten und meinen eigenen Ergebnissen:

  1. Mit meinem Ansatz scheint es kein Problem zu geben. Insbesondere schreibt C vor, dass Strukturfelder niemals die Reihenfolge ändern.

  2. Man könnte auch (wie von einer Antwort vorgeschlagen) vom letzten persistenten Feld zählen und seine Größe hinzufügen: (char*)&myst.x2 + sizeof(&myst.x2) - (char*)(&myst) . Das wäre äquivalent, außer dass es nicht die Füllbytes (falls vorhanden) für das letzte Feld enthalten würde. Ein sehr kleiner Vorteil - und ein sehr kleiner Nachteil darin, weniger einfach zu sein.

  3. Aber die akzeptierte Antwort mit offsetof scheint mir vorzuziehen. Es ist klar-expressive und reine Kompilierzeit, es erfordert keine Instanz der Struktur. Es scheint weiterhin Standard zu sein, der in jedem Compiler verfügbar ist. Wenn ein Kompilierzeitkonstrukt nicht benötigt wird und eine Instanz der Struktur verfügbar ist (wie in meinem Szenario), sind beide Lösungen im Wesentlichen äquivalent.

leonbloy 02.02.2011, 20:12
quelle

5 Antworten

10

Haben Sie sich die Einrichtung offsetof angeschaut? Sie gibt den Offset eines Elements vom Anfang einer Struktur zurück. So gibt offsetof (st, x2) den Offset von x2 vom Start der Struktur zurück. In Ihrem Beispiel gibt offsetof (st, x2) + sizeof(st.x2) die Anzahl der Bytes der serialisierten Komponenten an.

Das ist ziemlich ähnlich zu dem, was Sie jetzt tun, Sie müssen nur die Auffüllung nach x2 ignorieren und ein selten verwendetes Stück C verwenden.

    
sbass 02.02.2011, 20:23
quelle
5

C garantiert diese Art von Verhalten. Es ist beabsichtigt, primitiven Polymorphismus zuzulassen. Überlegen Sie:

%Vor%     
Puppy 02.02.2011 20:18
quelle
3

Der C-Compiler kann Padding-Bytes für die Ausrichtung einfügen, aber die Strukturvariablen nicht neu anordnen.

Ein saubererer Weg könnte sein, einfach eine zweite Struktur für sizeof () Zwecke zu definieren, die die Anfangsvariablen der gewünschten Struktur enthält. Der Compiler garantiert, dass 2 Struts, die die gleichen Variablen in der gleichen Reihenfolge haben, auf die gleiche Weise angeordnet werden.

    
payne 02.02.2011 20:19
quelle
0

Vielleicht möchten Sie sich protobuf ansehen; es scheint zu tun, was Sie in einer tragbaren Art und Weise wollen.

    
James 02.02.2011 20:17
quelle
0

Ich stimme für das KISS-Prinzip. Schreiben Sie in die Datei Element für Element und Sie sind garantiert keine Compiler-Abhängigkeiten.

    
Karl Bielefeldt 02.02.2011 20:25
quelle

Tags und Links