PDA

View Full Version : [C] struct, fread e il misterioso caso di float


Duchamp
14-01-2011, 21:59
Ciao a tutti e perdonatemi il titolo pittoresco!
Mi trovo di fronte ad un caso stranissimo: ho una struct di questo tipo:


struct Data {
char txt[9];
float val;
..... (altri dati)
} data;


che vado a scrivere in binario su un file. Nessun problema.
Poi in un altro momento voglio leggerne i primi due valori: apro il file e procedo con fread:


FILE *fh = fopen(......, "rb");
char tmp_txt[9];
float tmp_val;
fread(&tmp_txt, sizeof(char), sizeof(tmp_txt), fh);
res = fread(&tmp_val, sizeof(float), 1, fh);


Nessun problema anche per il tmp_txt, ma incomprensibili (per me) risultati nel float. Dopo un po' di analisi con editor esadecimali ho notato che all'interno del file binario il valore che voglio pescare è al byte con offset 12 (char da 0 a 8, float da 9 a 12) ma il programma legge, per il float, ciò che sta a offset 9, ovvero esattamente dopo la stringa.
Workaround trovato fino ad ora: aggiungere
fseek(fh, 3, SEEK_CUR);
tra una chiamata di fread e l'altra.

Io sinceramente non me lo so spiegare; sarà che è la prima volta che scrivo float in binario, sarà che google non mi ha mostrato nulla di utile se non una questione relativa al padding delle struct... potrebbe essere?

Spero possiate darmi qualche informazione in più!
Vi ringrazio in anticipo :)

AngeL)
14-01-2011, 22:54
google non mi ha mostrato nulla di utile se non una questione relativa al padding delle struct... potrebbe essere?

Colpito e affondato! :D

Vedi wiki (http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86) e anche qui (http://allinterview.com/showanswers/62991.html)

#pragma pack(push,1)
struct //...
#pragma pack(pop)
dovrebbe far risparmiare al compilatore quei preziosi byte :D

Duchamp
14-01-2011, 23:12
'orcamiseria! :D Lo sapevo...
Grazie AngeL) per i link, il primo mi era sfuggito ed è molto utile.
Ne approfitto per chiederti una cosa: la direttiva pragma la devo utilizzare al momento della definizione della struct? Quindi in un header file, nel caso la definissi lì?

marco.r
15-01-2011, 01:57
C'e' un motivo se il compilatore padda, per cui se non serve non "impacchettare".
Alla fine ti basta leggere nello stesso modo in cui hai scritto:
se scrivi i campi uno a uno leggi i campi uno a uno
se scrivi la struttura in un colpo (e quindi hai padding), leggi la struttura in un colpo (e quindi hai padding).
infine se il formato su disco e' specifico dell'applicazione... usa quel formato :D.

Duchamp
15-01-2011, 11:59
C'e' un motivo se il compilatore padda, per cui se non serve non "impacchettare".
Alla fine ti basta leggere nello stesso modo in cui hai scritto:
se scrivi i campi uno a uno leggi i campi uno a uno
se scrivi la struttura in un colpo (e quindi hai padding), leggi la struttura in un colpo (e quindi hai padding).
infine se il formato su disco e' specifico dell'applicazione... usa quel formato :D.

Ciao marco.r, dopo una notte di ragionamento anch'io preferirei non "snaturare" l'allineamento introdotto dal compilatore. L'unica sfiga consiste nel caso in cui stia leggendo i dati uno ad uno, dovendomi ricordare di saltare i buchi introdotti dal padding.
Adesso capisco perchè gli header di diversi file sono suddivisi in blocchi di 4 byte :cool:
Ringrazio tutti, ho risolto i miei dubbi.