einclude
einclude

Reputation: 1074

gcc 4.3.4 bug with structure size?

What's wrong with this code when I compile it with -DPORTABLE?

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    unsigned char data[11];

#ifdef PORTABLE
    unsigned long intv;
#else
    unsigned char intv[4];
#endif

} struct1;

int main() {

    struct1 s;

    fprintf(stderr,"sizeof(s.data) = %d\n",sizeof(s.data));
    fprintf(stderr,"sizeof(s.intv) = %d\n",sizeof(s.intv));
    fprintf(stderr,"sizeof(s) =      %d\n",sizeof(s));

    return 0;
}

The output I get on 32 bit GCC:

$ gcc -o struct struct.c -DPORTABLE
$ ./struct 
sizeof(s.data) = 11
sizeof(s.intv) = 4
sizeof(s) =      16
$ gcc -o struct struct.c 
$ ./struct 
sizeof(s.data) = 11
sizeof(s.intv) = 4
sizeof(s) =      15

Where did the extra byte came from?

I always thought 11+4 = 15 not 16.

Upvotes: 0

Views: 160

Answers (3)

Osman Turan
Osman Turan

Reputation: 1371

It's called alignment. That's especially added padding at end of structures to decrease cache misses. If you want to disable it, you can use something like that:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */

typedef struct {
  unsigned char data[11];

#ifdef PORTABLE
  unsigned long intv;
#else
  unsigned char intv[4];
#endif
} struct1;

#pragma pack(pop)   /* restore original alignment from stack */

Upvotes: 1

Alok Save
Alok Save

Reputation: 206546

This is due to structure padding.
Compilers are free to add extra padding bytes to structures to optimize the access time.

This is the reason You should always use sizeof operator and never manually calculate size of structures.

Upvotes: 2

Dan Fego
Dan Fego

Reputation: 14004

Nothing's wrong with the code; those sizes are correct. The compiler may add padding to structs at its discretion. The size of a struct is only guaranteed to be large enough to hold its elements, so adding the sizes of its elements is not a reliable way to get the size of the struct.

Such padding can be helpful in keeping elements and the structs themselves aligned to specific boundaries, both to avoid alignment errors (perhaps why it's enabled with -DPORTABLE) and as a speed optimization, as Als points out.

Upvotes: 4

Related Questions