Sizeof operator returns incorrect size?

21k Views Asked by At

Possible Duplicate:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
Extra bytes when declaring a member of a struct as uint32_t

For some reason, the sizeof operator returns a bogus size for this structure (48 instead of 40):

typedef struct mbdb_file_info {
  uint16_t mode;

  uint32_t unk0;
  uint32_t unk1;
  uint32_t user_id;
  uint32_t group_id;

  uint32_t time0;
  uint32_t time1;
  uint32_t time2;

  uint64_t length;
  uint8_t flag;
  uint8_t property_count;
} mbdb_file_info;

So here is a simple test:

printf("%ld %ld %ld %ld: %ld", sizeof(uint8_t),
                                sizeof(uint16_t), 
                                sizeof(uint32_t),
                                sizeof(uint64_t),
                                sizeof(mbdb_file_info));

Which prints:

1 2 4 8: 48

How does this happen? If you add all the sizes together you get 40, not 48. Where on earth does the 48 come from?

And if it's some weird x86-64 perk, how do I ensure that the all the fields of the structures occupy the amounts I want them to occupy (I'm casting a bunch of bytes to this structure)?

5

There are 5 best solutions below

3
On BEST ANSWER

The compiler may append some bytes in the middle of the struct in order to align the struct members. The size of the struct is at least the sum of he members' size, but not limited to it.

0
On

Alignment. Certain data types are aligned at certain boundaries (read: addresses divisible by a factor of 2, e.g. 16), dependent on the architecture, and this causes padding in the structure.

There are compiler options to suppress this behaviour, and the gcc documentation tells you how to use the aligned attribute for it.

0
On

This is called structure padding for alignment.

What is likely happening is that 8- and 16-bit values are padded to 32 bit and the whole structure is padded to be a multiple of machine word size (8).

0
On

Because of the structure padding (not sure which was the term here). The biggest field is 64bit, so everything's aligned according it. So, we have:

typedef struct mbdb_file_info {
  uint16_t mode; // 16 + 

  uint32_t unk0; // 32 = 48, so add 16 more to align to 64bit;
  uint32_t unk1; // this
  uint32_t user_id; // and this give 64bits ;
  uint32_t group_id; // again this

  uint32_t time0; // plus this - 64bits;
  uint32_t time1; // this 
  uint32_t time2; // and this = 64bit ;

  uint64_t length; // this is 64 by itself
  uint8_t flag;  // this
  uint8_t property_count; // +this is 16, add 48 for the alignment
} mbdb_file_info; // when you sum all bits (+ the additional for padding)
                      // you have exactly 48B
0
On

You can also get rid of the padding by re-ordering your struct members. For example, if you declare the 64-bit, then 32's, then 16, then 8's, it will be naturally aligned and not have extra padding bytes.