Arthur J. O'Dwyer said:
Of course not. Luckily, you don't need to. If you think you do,
then explain your problem, and we can try to help you solve it. But
the only reason to be worried about pointer alignment is if you're
implementing 'malloc' and friends, and in that case you don't need
to worry about portability (and there are well-known tricks with
'union' to help you cope).
I have a similar problem, that I'll have to resolve soon.
I build a transactional storage and I store my data on disk pages.
My system is layered, ie. paging and caching is on the bottom,
then transaction processing, and logical structure (eg. hash table,
btree etc.) on top. Each higher level layer obtains a page (or
rather part of a page that it is allowed to manage) from lower
level; in this sense it is malloc-like problem.
The page may look more-or-less like this (symbolically):
[address +0]
struct transaction_header t_h;
struct structure_header s_h;
struct data0_header d_h0;
char data0[*];
size_t int0;
struct data1_header d_h1;
char data1[*];
size_t int1;
[address +free_offset]
... ("free" space)
[address +free_offset + free_size]
size_t ptr1;
size_t ptr0;
struct transaction_footer t_f;
[address +page_size]
I don't want to do manual data "packing", because that would cost
additional cpu cycles (currently memory transfers take most of
the time); I want to access the data in machine native format
directly on page (cross-platform portability of the data is irrelevant).
Problems to solve:
(Suppose transaction_header starts at malloc()'ed address, thus is
aligned for any data type, and it is known.)
1. When transactional layer passes a page to structure layer,
it has to pass an address (here: for structure_header) aligned
for any data type (this is easy, I have to embed a most alignment
requiring type via a union into transaction_header).
2. I have to somehow calculate the address for transaction_footer, which
has to be fit at the very end of the page.
I could do this like this:
(struct transaction_footer*)address
+ (page_size/sizeof(struct transaction_footer) - 1)
3. After I write data0, I have to find an address for int0 and d_h1.
The general issue is that I might have a sequence of different
types. The solution is practically same as in 2., but I have
to keep "most aligned" reference pointer (here: transaction_header,
or structure_header), which might be a little nuisance.
4. I have to pre-calculate the needed space. This seems the most
difficult part to make in portable C.
Suppose I have d_hN, dataN and intN (and ptrN) to store on a page.
The transactional layer can return free_size and free_offset before
it takes any other action (suppose they're cached somewhere);
it doesn't know about structure's alignment requirements.
Now, how could I check if my data would fit in the free space?
For the first thing: the actual size needed depends on the value
of [address+free_offset] (for d_hN might not start exactly there);
for the second: I cannot do pointer arithmetic without having
a *valid* pointer (to make it Standard compliant I would have
to allocate memory for arithmetic purposes only, which is out of
the question). Doing "integer pointer" arithmetic seems
the only solution.
Is there a C solution to a more generic problem: Having a pointer (void*)
and a data_type, calculate the nearest position after the pointer
at which we may put a datum of data_type? If yes, can we do it (ie.
calculate) without having (enough) valid memmory allocated?
I'd be more than happy to hear ideas on these issues. TIA