Search code examples
carraysstructfwrite

C fwrite() won't save every data in the file


int nrAnimals = 0;
ANIMAL animals[10];
addTestData(animals, &nrAnimals);

static void addTestData(ANIMAL* animals, int* nrAnimals)
{
ANIMAL a1 = {"Max", Dog, Male, 12, "Schoolstraat 1", {1, 2, 3}};
ANIMAL a2 = {"Kiekerjan", Cat, Female, 4, "boven in boom", {4, 3, 2}};
ANIMAL a3 = {"Lorre", Parrot, Male, 40, "werk", {8, 9, 10}};
ANIMAL a4 = {"Fifi", Dog, Female, 1, "1Kerkstraat 13", {1, 1, 100}};
ANIMAL a5 = {"Piep", GuineaPig, Male, 3, "1thuis", {3, 4, 1}};
ANIMAL a6 = {"Fifi", Dog, Female, 1, "2Kerkstraat 13", {1, 1, 100}};
ANIMAL a7 = {"Piep", GuineaPig, Male, 3, "2thuis", {3, 4, 1}};
ANIMAL a8 = {"Fifi", Dog, Female, 1, "3Kerkstraat 13", {1, 1, 100}};
ANIMAL a9 = {"Piep", GuineaPig, Male, 3, "3thuis", {3, 4, 1}};

animals[(*nrAnimals)++] = a1;
animals[(*nrAnimals)++] = a2;
animals[(*nrAnimals)++] = a3;
animals[(*nrAnimals)++] = a4;
animals[(*nrAnimals)++] = a5;
animals[(*nrAnimals)++] = a6;
animals[(*nrAnimals)++] = a7;
animals[(*nrAnimals)++] = a8;
animals[(*nrAnimals)++] = a9;
}


int writeAnimals(const char* filename, const ANIMAL* animalPtr, int nrAnimals)
 {
     if (filename == NULL || animalPtr == NULL || nrAnimals)
     {

     }
     FILE *fp;
     fp = fopen(filename, "w");
     fwrite(animalPtr, sizeof(ANIMAL),nrAnimals,fp);
     fclose(fp);
     return 0;
 }

above are the struct I want to include in my file. after I run this code and open the file with hexeditor I only see a lot of zero's.

File where I save the animals

Am I doing something wrong here?

edit:

void test_writeAnimals(void)
{
int nrAnimals = 0;
ANIMAL animals[10];
addTestData(animals, &nrAnimals);
int number;
FILE *fp;
number = writeAnimals("Argenis", animals, 10);
fclose(fp);
TEST_ASSERT_EQUAL(1, number);
}

this is how I call the function.

typedef enum
{
Cat,
Dog,
GuineaPig,
Parrot
} SPECIES;

typedef enum
{
Male,
Female
} SEX;

typedef struct
{
int Day;
int Month;
int Year;
} DATE;

#define MaxNameLength 25
#define MaxLocationLength 100
typedef struct
{
char    Name[MaxNameLength];
SPECIES Species;
SEX     Sex;
int     Age;
char    FoundAtLocation[MaxLocationLength];
DATE    DateFound;
} ANIMAL;

Solution

  • The function fwrite writes the fixed amount of data that you tell it. The unused space in the structures does not magically vanish.

    For example, the first member of the struct is

    char Name[MaxNameLength];
    

    so fwrite will write all 25 characters of Name to the file, regardless of the fact that the first animal's name "Max" has only 3 letters.

    The second member is Species which you initialised as Dog so has the value 1.

    The third member is Sex which you initialised as Male and has the value 0.

    Furthermore, the struct itself is padded so that each member is aligned to 32-bits, and the first member Name actually takes 28 bytes of the struct, not 25.

    So the first 28 bytes of the hex dump show "Max" of length 25 plus 3 bytes padding, followed by 01 00 00 00 which is the 32-bit value for Dog in little-endian format, followed by 00 00 00 00, the 32-bit value of Male.

    4D 61 78 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    01 00 00 00
    00 00 00 00
    

    and so on.