here are my structures
typedef struct buffer
{
char tab[b];
int suiv;
}buffer;
typedef struct header
{
int first ;
int nb_buff ;
int nb_insert ;
int nb_supp ;
int last ;
int pos ;
}header;
So I need to copy these structures in a binary file ,and then retrieve them afterward to make some treatments on them ,however I struggled to understand how fwrite and fread worked when the data given is a structure ,can anyone help me understand ?
CodePudding user response:
the structure is represented in the memory as a chunk of data. That chunk is sizeof(your_structure)
bytes long. It contains all members and padding.
fwrite
simple writes this chunk of memory to the file.
fread
reads this data from the file and stores in memory "reacreating" the structure as the layout it's memory layout is the same
CodePudding user response:
Have a look at the declaration of fwrite
:
size_t fwrite(
const void *restrict buffer, //pointer to the first object in the array to be written
size_t size, //size of each object
size_t count, //the number of the objects to be written
FILE *restrict stream //pointer to the output stream
);
cppreference says the following:
Writes count of objects from the given array buffer to the output stream stream.
The objects are written as if by reinterpreting each object as an array of unsigned char and calling fputc size times for each object to write those unsigned chars into stream, in order.
...
Note: the parameter buffer
is of type void*
, that means, only an address of a region (block) of memory is passed to fwrite
, no type information whatsoever. In other words, fwrite
does not know (care) of what is stored at the specific location.
CodePudding user response:
C allows you to memcpy
any object with an address or treat any such object as an array of a character type (char
, unsigned char
, signed char
).
That is, fwrite
can do:
size_t fwrite(
const void *restrict buffer, //pointer to the first object in the array to be written
size_t size, //size of each object
size_t count, //the number of the objects to be written
FILE *restrict stream //pointer to the output stream
) {
//...
memcpy(streams_internal_buffer, buffer, size);
//...
}
or (perhaps less efficiently, though a compiler might recognize such loops):
//...
for(size_t *p=(char*)buffer, *end=(char*)buffer size; p!=end;) *target = *p;
//...
Optimizing compilers need to treat memcpy-calls such loops magically because of their strict-aliasing implications.
They may generate for them either inline code or a call to a real memcpy
function.
Libc memcpy
implementations tend to be beneficial for large-range copying and are written in assembly or in specially annotated C (e.g., attribute((may_alias))
) or with small-fixed-sized memcpy
calls that must be locally (for the given compiler) known not to generate a real (recursive) call). Their aim is to copy via larger (word-sized) aligned chunks rather than char-by-char.