Home > other >  how does fwrite copy data in a file when it's a structure
how does fwrite copy data in a file when it's a structure

Time:12-27

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.

  • Related