In said:
This structure padding issue is bothering me now, could
not locate a satisfactory answer on clc, so here it goes...
I have a structure, given below:
typedef struct {
int flag;
char keys[3][9];
char padding[??];
} foo;
I need to fill in the size of padding array here so as to
make the entire structure size a multiple of 8. Is there
a way in which I can calculate the padding ? This structure
will be used on AIX 5.* and RHL.
Yes. It's not strictly guaranteed to work (it will fail if the struct
needs to be aligned to multiples of something greater than 8 or that is
not a power of two) and, in theory, the compiler may add some padding of
its own at the end, but in practice you can calculate the padding if the
compiler is happy with the idea of the structure size being a multiple of
8. In the worst case you may have to add 8 bytes of padding, because
you can't have arrays of size 0. Needless to say, the padding may
differ between implementations (but this is transparent to the source
code).
There is more than way of doing it, but I prefer the one that completely
virtualises the struct definition, at the expense of declaring an
auxiliary structure, mirroring the real one, first:
fangorn:~/tmp 155> cat test.c
#include <stdio.h>
#include <assert.h>
#include <stddef.h>
#define ALIGN 8
struct foo_aux {
int flag;
char keys[3][9];
char padding;
};
struct foo {
int flag;
char keys[3][9];
char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
};
int main()
{
assert(offsetof(struct foo_aux, padding) == offsetof(struct foo, padding));
assert(sizeof(struct foo) % ALIGN == 0);
printf("%d\n", (int)sizeof(struct foo));
return 0;
}
fangorn:~/tmp 156> gcc test.c
fangorn:~/tmp 157> ./a.out
32
The catch is that both struct definitions must be kept in sync, when
changes are made. This is actually tested by the first assert. If the
second assert fails, there is nothing you can do: the compiler is not
happy with a structure size that is a multiple of 8.
There is a way to automatically keep the two structures in sync, but I'm
not very fond of it: put the common part of the two declarations in a
separate file and include it. Change that file when you need to modify
the structure definition. It's a readability vs maintenability tradeoff.
fangorn:~/tmp 166> cat struct_foo.c
int flag;
char keys[3][9];
fangorn:~/tmp 167> cat test.c
#include <stdio.h>
#include <assert.h>
#include <stddef.h>
#define ALIGN 8
struct foo_aux {
#include "struct_foo.c"
char padding;
};
struct foo {
#include "struct_foo.c"
char padding[ALIGN - offsetof(struct foo_aux, padding) % ALIGN];
};
int main()
{
assert(sizeof(struct foo) % ALIGN == 0);
printf("%d\n", (int)sizeof(struct foo));
return 0;
}
fangorn:~/tmp 168> gcc test.c
fangorn:~/tmp 169> ./a.out
32
Dan