Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write raw struct contents (bytes) to a file in C. Confused about actual size written

Basic question, but I expected this struct to occupy 13 bytes of space (1 for the char, 12 for the 3 unsigned ints). Instead, sizeof(ESPR_REL_HEADER) gives me 16 bytes.

typedef struct {
  unsigned char version;
  unsigned int  root_node_num;
  unsigned int  node_size;
  unsigned int  node_count;
} ESPR_REL_HEADER;

What I'm trying to do is initialize this struct with some values and write the data it contains (the raw bytes) to the start of a file, so that when I open this file I later I can reconstruct this struct and gain some meta data about what the rest of the file contains.

I'm initializing the struct and writing it to the file like this:

int esprime_write_btree_header(FILE * fp, unsigned int node_size) {
  ESPR_REL_HEADER header = {
    .version       = 1,
    .root_node_num = 0,
    .node_size     = node_size,
    .node_count    = 1
  };

  return fwrite(&header, sizeof(ESPR_REL_HEADER), 1, fp);
}

Where node_size is currently 4 while I experiment.

The file contains the following data after I write the struct to it:

-bash$  hexdump test.dat
0000000 01 bf f9 8b 00 00 00 00 04 00 00 00 01 00 00 00
0000010

I expect it to actually contain:

-bash$  hexdump test.dat
0000000 01 00 00 00 00 04 00 00 00 01 00 00 00
0000010

Excuse the newbiness. I am trying to learn :) How do I efficiently write just the data components of my struct to a file?

like image 591
d11wtq Avatar asked Apr 14 '12 11:04

d11wtq


People also ask

How many bytes is a struct in C?

struct { unsigned int widthValidated; unsigned int heightValidated; } status; This structure requires 8 bytes of memory space but in actual, we are going to store either 0 or 1 in each of the variables. The C programming language offers a better way to utilize the memory space in such situations.

How much memory does a struct use in C?

Structure Padding Processor doesn't read 1byte at a time from memory.It reads 1 word at a time. In 32 bit processor, it can access 4 bytes at a time which means word size is 4 bytes. Similarly in a 64 bit processor, it can access 8 bytes at a time which means word size is 8 bytes.

How many bytes of memory does a struct take?

Above is the alignment of the structure A, and that's why the size of the struct is 32 Bytes. Also, the object a of type struct A is 32 Bytes.

How can we read write structures from to data files?

For writing in file, it is easy to write string or int to file using fprintf and putc, but you might have faced difficulty when writing contents of struct. fwrite and fread make task easier when you want to write and read blocks of data.


2 Answers

Microprocessors are not designed to fetch data from arbitrary addresses. Objects such as 4-byte ints should only be stored at addresses divisible by four. This requirement is called alignment.

C gives the compiler freedom to insert padding bytes between struct members to align them. The amount of padding is just one variable between different platforms, another major variable being endianness. This is why you should not simply "dump" structures to disk if you want the program to run on more than one machine.

The best practice is to write each member explicitly, and to use htonl to fix endianness to big-endian before binary output. When reading back, use memcpy to move raw bytes, do not use

char *buffer_ptr;
...
++ buffer_ptr;
struct.member = * (int *) buffer_ptr; /* potential alignment error */

but instead do

memcpy( buffer_ptr, (char *) & struct.member, sizeof struct.member );
struct.member = ntohl( struct.member ); /* if member is 4 bytes */
like image 195
Potatoswatter Avatar answered Sep 18 '22 23:09

Potatoswatter


That is because of structure padding, see http://en.wikipedia.org/wiki/Sizeof#Implementation

like image 20
Vincenzo Pii Avatar answered Sep 20 '22 23:09

Vincenzo Pii