[...]
Generally speaking, any structure is going to be aligned (i.e. start)
on the least restrictive type of address that the machine has
(typically an address that is a multiple of 4 or 8). This will often
be an address returned by malloc() and friends.
Not necessarily. If none of a structure's members require large
alignment, the structure itself won't necessarily require large
alignment. The compiler is free to align all structures on, say,
4-byte or 8-byte boundaries, but it's not required to.
A concrete example: this structure:
struct c { char c; };
has 1-byte alignment under gcc, and if you declare adjacent two
objects of this type, one of them will probably have an odd address.
You can typically minimize the padding by arranging the structure
members from largest to smallest. This tends to work because any
address suitable for, for example, a 32-bit integer also tends to be
suitable for a 16-bit integer, and any address suitable for a 16-bit
integer is suitable for a character.
struct memorywaster {
char c[3];
short a, b, c;
int x, y, z;
long p, d, q;
};
If you really want to waste memory, though, don't put members of the
same type together. Preceding each long by a char will typically
require sizeof(long)-1 bytes of padding.
e.g.:
#include <stdio.h>
#include <stddef.h>
typedef struct tragic_stupid {
char a;
unsigned long long b;
char c;
unsigned long long d;
char e;
unsigned long long f;
char g;
unsigned long long h;
char i;
unsigned long long j;
char k;
unsigned long long l;
char m;
unsigned long long n;
} badly_aligned_thingy;
int main(void)
{
printf("badly_aligned_thingy.a is at %u\n", offsetof
(badly_aligned_thingy, a));
printf("badly_aligned_thingy.b is at %u\n", offsetof
(badly_aligned_thingy, b));
printf("badly_aligned_thingy.c is at %u\n", offsetof
(badly_aligned_thingy, c));
printf("badly_aligned_thingy.d is at %u\n", offsetof
(badly_aligned_thingy, d));
printf("badly_aligned_thingy.e is at %u\n", offsetof
(badly_aligned_thingy, e));
printf("badly_aligned_thingy.f is at %u\n", offsetof
(badly_aligned_thingy, f));
printf("badly_aligned_thingy.g is at %u\n", offsetof
(badly_aligned_thingy, g));
printf("badly_aligned_thingy.h is at %u\n", offsetof
(badly_aligned_thingy, h));
printf("badly_aligned_thingy.i is at %u\n", offsetof
(badly_aligned_thingy, i));
printf("badly_aligned_thingy.j is at %u\n", offsetof
(badly_aligned_thingy, j));
printf("badly_aligned_thingy.k is at %u\n", offsetof
(badly_aligned_thingy, k));
printf("badly_aligned_thingy.l is at %u\n", offsetof
(badly_aligned_thingy, l));
printf("badly_aligned_thingy.m is at %u\n", offsetof
(badly_aligned_thingy, m));
printf("badly_aligned_thingy.n is at %u\n", offsetof
(badly_aligned_thingy, n));
return 0;
}
/* One possible output:
badly_aligned_thingy.a is at 0
badly_aligned_thingy.b is at 8
badly_aligned_thingy.c is at 16
badly_aligned_thingy.d is at 24
badly_aligned_thingy.e is at 32
badly_aligned_thingy.f is at 40
badly_aligned_thingy.g is at 48
badly_aligned_thingy.h is at 56
badly_aligned_thingy.i is at 64
badly_aligned_thingy.j is at 72
badly_aligned_thingy.k is at 80
badly_aligned_thingy.l is at 88
badly_aligned_thingy.m is at 96
badly_aligned_thingy.n is at 104
*/