1

I would like to write a binary image of a structure array to a binary file. I have tried this so far:

#include <stdio.h>
#include <string.h>
#define NUM 256

const char *fname="binary.bin";


typedef struct foo_s {
    int intA;
    int intB;
    char string[20];
}foo_t;



void main (void)
{
    foo_t bar[NUM];

    bar[0].intA = 10;
    bar[0].intB = 999;
    strcpy(bar[0].string,"Hello World!");

    Save(bar);
    printf("%s written succesfully!\n",fname);
}

int Save(foo_t* pData)
{
    FILE *pFile;
    int ptr = 0;
    int itr = 0;

    pFile = fopen(fname, "w");
    if (pFile == NULL) {
        printf("couldn't open %s\n", fname);
        return;
    }
    for (itr = 0; itr<NUM; itr++) {
        for (ptr=0; ptr<sizeof(foo_t); ptr++)
        {
            fputc((unsigned char)*((&pData[itr])+ptr), pFile);
        }
        fclose(pFile);
    }  
}

but the compiler is saying aggregate value used where an integer was expected fputc((unsigned char)*((&pData[itr])+ptr), pFile); and I don't quite understand why, what am I doing wrong?

Thanks!

4 Answers 4

2

Problem 1

Use the right mode for opening the file.

pFile = fopen(fname, "wb");

Problem 2

The call to fclose is in the wrong place.

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
  fclose(pFile);
}

You are closing the file after writing out the data of the first foo_t. Subsequent calls will result in undefined behavior since you will be calling fputc using a FILE* that has been closed.

The call to fclose must be moved out of the loops.

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
}
fclose(pFile);

Problem 3

The way you are trying to access a byte in the loops is incorrect. Here are the loops:

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
}

Here's the line you are trying to get a byte.

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                           ^           ^
                           This is of type `foo_t*`

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                          ^                 ^
                          This pointer arithmetic is done on `foo_t*`.
                          It is not pointer arithmetic done on `char*`.
                          You are going to run into out of bound memory access
                          very quickly.

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                         ^                  ^
                         This is dereferencing a `foo_t*`, which
                         means it is of type `foo_t`.

You are getting the compiler error since you are trying to cast a foo_t to an unsigned char.

To save a foo_t, you can take two approaches. You can use fwrite to save an entire foo_t in one call.

for (itr = 0; itr<NUM; itr++) {
  fwrite(&(pData[itr]), sizeof(foo_t), 1, pFile);
}

If you must write each byte using fputc, which I don't think is needed, you will have to change your code a little bit.

The following should work:

for (itr = 0; itr<NUM; itr++) {
  cp = (char*)&pData[itr];  // Declare char* cp in the function.
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc(cp[ptr], pFile);
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1
  1. Ensure file is opened in binary mode.

    // pFile = fopen(fname, "w");
    pFile = fopen(fname, "wb");
    
  2. Cast to char * pointer before indexing. Original code indexes by the sizeof(pData[itr]). [Edit] and then dereferenced the type - then tries to cast to unsigned char @R Sahu

    //fputc((unsigned char)*((&pData[itr])+ptr), pFile);
    unsigned char *p = (unsigned char *) (&pData[itr]);
    fputc(p[ptr], pFile);
    
  3. As @R Sahu pointed out: fclose() should be moved outside the loops.

Minor:

  1. Recommend passing NUM is as argument to save().

  2. foo_t bar[NUM]; is not fully initialized.

  3. The non-loop solution is

    if (fwrite(pData, sizeof(*pData), NUM, pFile) == NUM) Success();
    
  4. Suggest making const: `int Save(const foo_t* pData)

  5. Better to use size_t for ptr & itr

1 Comment

See @R Sahu concerning mis-placed fclose(). Also that answer's explanation concerning the compiler error is more correct. The solution is the same.
1

To write into the binary file you need to open the file in w+b mode. and then use fwrite to write into the file. It should work.

pFile = fopen(fname, "w+b");

Instead of fputc use fwrite.

fwrite ((foo_t *)&pData[itr], sizeof(foo_t), 1, pFile);

2 Comments

error: subscripted value is neither array nor pointer nor vector fwrite(pData[itr][ptr], sizeof(foo_t), 1, pFile);
dont use the inner for loop.
0

i think all you need to do is just write it.

foo_t fooarry[SOME_SIZE];

fd = open(fname, O_WRONLY);
write(fd, fooarry, SOME_SIZE * sizeof(foo_t));

UPDATE: if you want to use file stream, go like this:

fwrite(fooarry, siezeof(foo_t), SOME_SIZE, pFile);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.