struct S {
size_t len;
type-X buf[0];
};
という状況下で、

size_t const len = 500;
struct S* const p = (struct S*)malloc(sizeof(struct S) + sizeof(type-X)*len);

p->len = len;
p->buf = (type-X*)((size_t)p + sizeof(struct S));

という処理を偶に見かけますが、これだと末尾パディングの影響でbuf[1]のアドレスがtype-Xのアライメントに沿っていない可能性があるので、不正な気がします
具体的には

struct S {
size_t len;
type-X* buf;
};
として、

size_t const len = 500;
size_t const padding_for_align_x = alignof(type-X)*(sizeof(struct S)%alignof(type-X) == 0 ? 0 : 1);
struct S* const p = (struct S*)malloc(sizeof(struct S) + padding_for_align_x + sizeof(type-X)*len);

p->len = len;
p->buf = (type-X*)((size_t)p + sizeof(struct S) + padding_for_align_x);

...などとしないとアライメント違反になりそうな気がするのですが、この認識は正しいでしょうか