Reputation: 1365
I know that there have been many questions about this topic, but I still find myself confused.
I have written this simple program to help me visualize memory alignment in C:
#include <stdio.h>
#include <stdlib.h>
struct S{
int a;
short b;
char c;
};
int main()
{
struct S *s;
posix_memalign((void**)&s, 8, 12) == 0 ? printf("allocation successful"):printf("allocation failed");
printf("\nlocation of struct:\t%p\n", s);
printf("\nlocation of int:\t%p\nlocation of short:\t%p\nlocation of char:\t%p\n", &(s->a), &(s->b), &(s->c));
printf("\nsizeof struct: %lu\n", sizeof(s));
free(s);
return 0;
}
This is working well, but I am getting confused with the alignments.
Using these arguments (alignment=8 bytes, size=12):
allocation successful
location of struct: 0x205e010
location of int: 0x205e010
location of short: 0x205e014
location of char: 0x205e016
sizeof struct: 8
The int
is the largest element of the struct, at 4 bytes. I can see here that the short
begins 4 bytes later, and the char
2 bytes after that. Why isn't there another 2 bytes of padding between the short
and char
?
Also, why does the allocation fail if I use an alignment of 4 bytes? Since that is the size of the largest element in the struct
, shouldn't it work?
allocation failed
location of struct: (nil)
location of int: (nil)
location of short: 0x4
location of char: 0x6
sizeof struct: 8
Upvotes: 1
Views: 874
Reputation: 755006
The char
member can be aligned on any byte boundary; there is never a need to insert padding before a char
member, even though a compiler could if it wanted to. The way it is laid out, there is just a single padding byte in the structure. If there was a gap after the short
member, the structure would have five bytes of padding, which is wasteful.
The chances are that the minimum alignment that posix_memalign()
supports is 8 on your machine. POSIX says it can fail:
[EINVAL]
The value of the alignment parameter is not a power of two multiple ofsizeof(void *)
.
Having said that, it looks like sizeof(void *)
is probably 4 (the addresses you print fit in a 32-bit address space). Maybe you should print errno
(and/or strerror(errno)
) to see what the cause of failure is.
Upvotes: 1