Puse todo el código pero, por supuesto, está en archivos diferentes (archivos .h y .c )
typedef unsigned char ubyte; typedef unsigned int uint; #include<stdbool.h> typedef struct Cube { ubyte n; ubyte e; ubyte s; ubyte w; } Cube; typedef struct Piece { Cube c; bool is_main; char offset_n; char offset_s; } Piece; typedef struct Block { ubyte total; Piece* pieces; } Block; Block *block_create(uint nb_pieces) { Block *block = malloc(sizeof(Block) + (sizeof(Piece) * nb_pieces)); block->pieces = (Piece *) (&block + sizeof(Block)); return block; } Me pregunto si esta línea de código: block->pieces = (&block + sizeof(Block)); estará siempre a salvo. Quiero decir: ¿podemos estar seguros de que, inmediatamente después de sizeof(Piece) , tendremos precisamente (sizeof(Piece) * nb_pieces) ? ¿Estamos seguros de que nunca habrá un problema de alineación (es decir, tal vez si está alineado en 64 bits, la memoria para sizeof(Block) será inferior a 8 bytes y block->pieces no debería apuntar exactamente a sizeof(Block) , pero " sizeof(Block) 64 bits alineados").
Espero ser lo suficientemente claro.
Primero, esto no está haciendo lo que esperas, y por múltiples razones:
block->pieces = (&block + sizeof(Block)); Primero, &block es la dirección de la variable block , no el contenido de block , y tiene el tipo block ** . A lo sumo, puede agregar con seguridad 1 valor de este puntero porque cualquier otra cosa creará un puntero más allá del final de esta variable que no es válido.
Entonces necesitarías cambiar &block a block . Eso aún no hará lo que espera porque la aritmética de punteros incrementa la dirección sin procesar en múltiplos del tamaño del objeto. Por lo tanto, agregar sizeof(Block) a esto no es mover hacia arriba 1 elemento de la matriz, sino mover hacia arriba los elementos de la matriz sizeof(Block) .
Para solucionar esto, necesitaría block + 1 . Ahora debe comenzar a preocuparse por la alineación. Para que su matriz de Pieces se alinee correctamente, debe verificar si _Alignof(Block) y _Alignof(Piece) son iguales. De lo contrario, deberá agregar bytes de relleno:
int padding = 0; if (_Alignof(Block) % _Alignof(Piece) != 0) { padding = _Alignof(Piece) - (_Alignof(Block) % _Alignof(Piece)); } Block *block = malloc(sizeof(Block) + padding + (sizeof(Piece) * nb_pieces)); block->pieces = (Piece *)((char *)(block + 1) + padding); Por supuesto, puede evitar todo esto haciendo que el miembro de pieces sea un miembro de matriz flexible :
typedef struct Block { ubyte total; Piece pieces[]; } Block;Y la asignación por sí sola será suficiente.