Dereferencing pointers to structs returned by C functions / Danger of misalignment?

No, I meant the pointer to the struct being aligned (according to the same rules Rust demands for that type when using #[repr(C)].


Let me provide an example of some C code I have written (to demonstrate my question):

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    int a;
    char b;
} foo_t;

foo_t *new_foo() {
    foo_t *ptr = calloc(1, sizeof(*ptr));
    ptr->a = 7;
    ptr->b = 12;
    return ptr;
}

void double_foo(foo_t **first, foo_t **second) {
    foo_t *x, *y, *dbl;
    x = new_foo();
    y = new_foo();
    dbl = calloc(2, sizeof(*dbl));
    memcpy(dbl+0, x, sizeof(*x));
    memcpy(dbl+1, y, sizeof(*y));
    free(x);
    free(y);
    memmove((void *)(dbl+1)-1, dbl+1, sizeof(*y));
    *first = dbl;
    *second = (void *)(dbl+1)-1;
}

int main() {
    foo_t *x, *y;
    double_foo(&x, &y);
    printf("x = %p\n", x);
    printf("y = %p\n", y);
    printf("x.a = %i\n", x->a);
    printf("x.b = %hhi\n", x->b);
    printf("y.a = %i\n", y->a);
    printf("y.b = %hhi\n", y->b);
    return 0;
}

(Edit: moved free invocation to be called after memcpy; output is still the same as shown below)

When I compile this C code on my system, I get:

x = 0x800a09000
y = 0x800a09007
x.a = 7
x.b = 12
y.a = 7
y.b = 12

Here, y is not aligned (and apparently I can work with that in C). Yet it's what's returned by double_foo. Maybe this is generally undefined behavior in C though? (I don't know enough about alignment in C to answer that question.)

I understand that when I use calloc, the data will be aligned. But if I have a general API description that returns a pointer to some struct, can I be sure that the data will be aligned as well (when I don't know how the function internally works)? Aparently not, as the example above shows. But will this ever happen in practice?