Reputation: 1074
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
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
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
Reputation: 14004
Nothing's wrong with the code; those sizes are correct. The compiler may add padding to struct
s 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