Und eine Datei, die genau so formatiert ist wie die struct header.
Wie kann ich nun am Besten die 12 Byte aus der Datei lesen und die Werte
in die Struct übernehmen?
Ich steh arbeite gerade das erste mal mit Strukturen..
Würde mich freuen wenn mir da jemand einen Tipp geben kann ;)
ciao
johannes
Die Frage ist nicht so einfach, wie sie zunächst aussieht. Denn es gibt
so allgemein keine
> Datei, die genau so formatiert ist wie die struct header.
„So allgemein keine“, weil mit „so formatiert wie“ Dinge nicht
spezifiziert sind wie Byte Order (ist das Byte auf der niedrigsten
Adresse das Byte mit der höchsten Wertigkeit? Bei x86 und AVR: nein,
wenn die Bytes vom Netz kamen oder der 68xx(x)/Coldfire-Familie: ja).
Du musst also das Layout genauer spezifizieren, ebenso (wegen Padding)
die Quell- und Zielarchitektur samt Compiler und dessen Optionen und
davon abhängig dann konvertieren.
Du sagst also am besten ein konkretes Beispiel, an dem entlang sich eine
Lösung überlegen lässt.
Für etwas allgemeinere Lösungen gibt es dann noch htons(), ntohs() usw.
Diese lösen compilerübergreifend das Problem der Byte Order, nicht aber
des Paddings. Zudem musst Du jedes struct-Element einzeln
durchschicken.
Also sieht der Hexdump der Datei folgendermaßen aus:
00 4e 61 bc 88 13 74 65 73 74 20 20
Und das möchte ich nun so in die Struct einlesen..
Ich hab gedacht dafür gibt es vllt eine einfache Möglichkeit..
viele grüße ;)
johannes schrieb:> ich habe folgende struct:struct header> {> uint32_t size;> uint16_t offset;> char name[6];> };>> Und eine Datei, die genau so formatiert ist wie die struct header.
Sicher? beim PC würde ich fast wetten das zwischen offset und name 2
Padding Bytes eingeschoben werden. Ausserdem hat der PC eine Little
endian Darstellung. Das ist auch nicht unbedingt das was man tippen
würde wenn man die Datei Manuell Bearbeitet. Spezifizier doch mal die
Datei und das System auf denn du Arbeitest. Dann können wir dir sicher
besser Helfen,
Intressant ist zum beispiel wie die Formatierungs in der datei sind
fälle wie size =31 ,offset =2 steht das nun als 312 in der Datei oder
als
31 2 oder 31\n 2\n und wenn da 312 steht,wie unterscheidest du das nun
von size 3 offset 12 ( Ich weiß das das unlogisch ist! aber dein
Programm ggf. nicht.)
generell hilft es wahrscheinlich für eine Quick and Dirty lösung den
Kompiler zu sagen das man die struct packet haben will und die Zahlen
mit führenden Nullen zu speichern, und die fehlenden Buchstaben des
Namens mit '\0' zu füllen.
beim gcc geht das gepackt so :
1
structheader
2
{
3
uint32_tsize;
4
uint16_toffset;
5
charname[6];
6
}__attribute__((packed));
das könnte man wahrscheinlich mit denn Führenden Nullen bei den Zahlen
und den '\0' bei den Name einfach so in den Speicher Der Struktur
Kopieren. Gegeben falls müssen noch die Endianess beachtet und
umgemodelt werden,
Ich habe mal deine struct genommen und mir unter Linux mit
gcc 4.3 davon sizeof ausgeben lassen.
1
#include<stdlib.h>
2
#include<stddef.h>
3
#include<stdio.h>
4
#include<stdint.h>
5
6
structheader
7
{
8
uint32_tsize;
9
uint16_toffset;
10
charname[6];
11
};
12
13
intmain(intnargs,char**args)
14
{
15
printf("%d\n",sizeof(structheader));
16
return0;
17
}
Ergebnis: 12 Byte
D.h., daß du in diesem einen Fall die Warnungen in den Wind
schlagen kannst und einfach mit fread aus der Datei in die struct
lesen kannst.
Das
__attribute__((packed));
würde ich drin lassen, um vorzubeugen, dass es mit einem späteren
gcc-Compiler auch geht. Tut ja nicht weh. In ein paar Jahren haben wir
vielleicht 64-Bit- oder (von mir aus) auch 256-Bit-Alignments.
Hi
Hc Zimmerer schrieb:> Das>> __attribute__((packed));>> würde ich drin lassen, um vorzubeugen, dass es mit einem späteren> gcc-Compiler auch geht. Tut ja nicht weh. In ein paar Jahren haben wir> vielleicht 64-Bit- oder (von mir aus) auch 256-Bit-Alignments.
Es gibt bei genau dieser Struktur für den Compiler eigentlich keinen
Grund Padding Bytes einzufügen. Jedes Element kommt auch ohne Padding
auf passende Offsets.
Bei
1
structheader2
2
{
3
charname[6];
4
uint32_tsize;
5
uint16_toffset;
6
};
sieht das aber schon ganz anders aus. __attribute__((packed)) kann
einen aber auch mal ärgern wenn man auf Maschinen unterwegs ist die gar
keine "ungeraden" Zugriffe erlauben (z.B. ARM9, MIPS)
Matthias
Μαtthias W. schrieb:> Es gibt bei genau dieser Struktur für den Compiler eigentlich keinen> Grund Padding Bytes einzufügen.
Derzeit. Du gehst von dem aus, was heute üblich ist. Schon ein
32-Bit-Alignment würde nicht mehr passen, und das gibt es schon. Nicht
umsonst sprach ich von zukünftigen Veränderungen und (als willkürliches
Beispiel) 64/256-bit-Alignments.
> __attribute__((packed)) kann einen aber auch mal ärgern
Spätestens dann war's mit dieser Methode Essig.
Hc Zimmerer schrieb:> Μαtthias W. schrieb:>> Es gibt bei genau dieser Struktur für den Compiler eigentlich keinen>> Grund Padding Bytes einzufügen.>> Derzeit. Du gehst von dem aus, was heute üblich ist. Schon ein
Nö. Eher von technischen Gegebenheiten.
> 32-Bit-Alignment würde nicht mehr passen, und das gibt es schon. Nicht
???
> umsonst sprach ich von zukünftigen Veränderungen und (als willkürliches> Beispiel) 64/256-bit-Alignments.
Warum sollte ein 16 Bit Datentyp mehr als 2 Byte Alignment benötigen?
Und wie realisiert man in diesem Fall ein uint16_t arr[16];? Padding
zwischen jedem Element? IIRC ist das laut C Standard garnicht möglich da
Du wirfst arrays, Pointerarithmetik und structs zusammen und rührst um.
Dann soll eine Pointerarithmetik dafür herhalten, dass eine struct nicht
auf 32 Bits gepaddet wird. Das scheint mir wenig sinnvoll.
Warum auf 32 Bits gepaddet werden soll? Weil in einem 32 Bit breiten
Speicher ein 32-Bit-Zugriff auf eine modulo-4-Adresse (Bit 1 und Bit 0
auf 0) in einem Zugriff zu erledigen ist, auf einer Adresse mit
gesetztem Bit 1 aber 2 Zugriffe benötigt.
Und lass mir bitte Arrays raus, wenn es um das Padding von structs geht.
Die haben nichts miteinander zu tun. Ich möchte es auch insgesamt dabei
bewenden lassen.