views:

415

answers:

4

How do I fwrite a struct containing an array

#include <iostream>
#include <cstdio>

typedef struct {
  int ref; 
  double* ary;
} refAry;

void fillit(double *a,int len){
  for (int i=0;i<len;i++) a[i]=i;
}

int main(){
  refAry a;
  a.ref =10;
  a.ary = new double[10];
  fillit(a.ary,10);
  FILE *of;
  if(NULL==(of=fopen("test.bin","w")))
     perror("Error opening file");
  fwrite(&a,sizeof(refAry),1,of);

  fclose(of);
  return 0;
}

The filesize of test.bin is 16 bytes, which I guess is (4+8) (int + double*). The filesize should be 4+10*8 (im on 64bit)

~$ cat test.bin |wc -c
16
~$ od -I test.bin 
0000000                   10             29425680
0000020
~$ od -fD test.bin -j4
0000004   0,000000e+00   7,089709e-38   0,000000e+00
                     0       29425680              0
0000020

thanks

+1  A: 

Your structure doesn't actually contain an array, it contains a pointer. If you really want variable-length structures, you'll need to keep a size field in there so that you know how big it is. The C FAQ has an example of exactly what it looks you're trying to do. In your case it might look something like this:

typedef struct {
    int ref; 
    double ary[1];
} refAry;

#define SIZE_OF_REFARY (sizeof(refAry) - sizeof(double))

To allocate:

size_t alloc_size = SIZE_OF_REFARY + 10*sizeof(double);
refAry *a = malloc(alloc_size);
a->ref = 10;

To write:

fwrite(a, SIZEP_OF-REFARY + a->ref * sizeof(double), 1, file);
Carl Norum
Check his code, `ref` acts as the size field. BTW, this code is a total hack, I don't think it should be recommended.
Manuel
Oh yeah, ok. I'll go clean that up. I'll go along with not recommended, but it's definitely popular; there's a *lot* of code out there that behaves this way.
Carl Norum
+2  A: 

You are writing the pointer (a memory address) into the file, which is not what you want. You want to write the content of the block of memory referenced by the pointer (the array). This can't be done with a single call to fwrite. I suggest you define a new function:

void write_my_struct(FILE * pf, refAry * x)
{
    fwrite(&x->ref, sizeof(x->ref), 1, pf);
    fwrite(x->ary, sizeof(x->ary[0]), x->ref, pf);
}

You'll need a similar substitute for fread.

Manuel
A: 

Your structure contains a pointer, not an array of 10. the sizeof() picks that up.

You'll need something like fwrite(a.ary, sizeof(double), 10, of); in order to write the actual array

Liz Albin
A: 

If the size of the array is always 10, then simply change your struct to:

typedef struct {
  int ref; 
  double ary[10];
} refAry;

You can then write this out with a single call to fwrite, using sizeof(refAry) for the size.

anon
I guess he wants to have a dynamic array, otherwise he doesn't need to store the size (`ref`).
Manuel