Why said:
Thanks Richard. In fact I was reading someone else's code. The
intention of the code is to have a memory allocation similar to this:
|<- SomeStruct ->|<- UserStruct ->
Hence,
SomeStruct *p;
p = malloc(sizeof(SomeStruct) + sizeof(UserStruct)); /* UserStruct can
be anything */
...
free(p);
(p+1) points to the beginning of UserStruct, so users can store
anything in there.
My understanding is, the paddings (if any) for memory alignment are
included in the calculation of sizeof(). So the code should work
properly. Is my understanding correct?
Padding bytes are part of the struct, and so are included
in the sizeof count. But that doesn't solve the problem of
getting proper alignment for the UserStruct part! Imagine
typedef struct { int x; } SomeStruct;
typedef struct { double y; } UserStruct;
and suppose (1) that there are no padding bytes, (2) that an
int occupies four bytes and must be aligned on a four-byte
boundary, and (3) that a double occupies eight bytes and must
be aligned on an eight-byte boundary. Then the code above will
request twelve bytes, and the allocated memory will begin on an
eight-byte boundary (because the memory returned by malloc() is
properly aligned for any use whatever, hence it's aligned at
least as strictly as a double would require). If p points to
an eight-byte boundary, then p+1 points four bytes further
along, to a four-byte boundary that is not an eight-byte
boundary, and a UserStruct can't begin there.
Things will work all right if UserStruct's alignment is no
stricter than SomeStruct's, but there's no a priori way to know
that this is true. If the actual type of UserStruct is known
(and not just its size), the simplest approach may be
struct { SomeStruct s; UserStruct u; } *p;
p = malloc(sizeof *p);
if (p == NULL) ...
p->s.x = 42;
p->u.y = 42.0;
...
free (p);
In a situation where only sizeof(UserStruct) is known and
not its actual type, a traditional but slightly iffy approach
is to try to figure out what the strictest alignment is:
typedef struct {
int i; long l; long long ll;
float f; double d; long double ld;
char *cp; int *ip; long *lp; long long *llp;
float *fp; double *dp; long double *ldp;
struct whocares *sp;
union whoknows *up;
void (*funcp)(void);
} Worst;
#define PADDED(n) ( ((n) + sizeof(Worst) - 1) \
/ sizeof(Worst) * sizeof(Worst) )
SomeStruct *p = malloc(PADDED(sizeof(SomeStruct))
+ size_of_user_struct);
if (p == NULL) ...
/* Now p points to the SomeStruct, and
* (char*)p + PADDED(sizeof(SomeStruct))
* points to the UserStruct
*/
One drawback to this approach is that it may overestimate
the strictness of UserStruct's alignment. Another is that it's
not possible to enumerate all possible types in the Worst
definition ...