Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

184
Visualizações
malloc and C alignment: is this hand-made optimization safe?

I put the whole code but, of course, it's in different files (.h and .c files)

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;
}

I am just wondering if this line of code: block->pieces = (&block + sizeof(Block)); will be always safe. I mean: can we be sure that, immediately after the sizeof(Piece), we will have precisely (sizeof(Piece) * nb_pieces)? Are we sure there will never be an alignment problem (ie maybe if it's 64-bits aligned, the memory for sizeof(Block) will be less than 8 bytes and the block->pieces should not point to exactly sizeof(Block), but "sizeof(Block) 64 bits-aligned").

I hope I'm clear enough.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

First, this isn't doing what you expect, and for multiple reasons:

block->pieces = (&block + sizeof(Block));

First, &block is the address of the variable block, not the contents of block, and has type block **. At most, you can safely add 1 this pointer value because anything more will create a pointer past the end of this variable which is invalid.

So then you would need to change &block to block. That still won't do what you expect because pointer arithmetic increments the raw address by multiples of the object size. So adding sizeof(Block) to this is not moving up 1 array element but moving up sizeof(Block) array elements.

To fix this you would need block + 1. Now you need to start worrying about alignment. For your array of Pieces to be aligned properly, you would need to check if _Alignof(Block) and _Alignof(Piece) are the same. If not, you would need to add padding bytes:

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);

Of course, you can avoid all this by making the pieces member a flexible array member:

typedef struct Block {
    ubyte total;
    Piece pieces[];
} Block;

And the allocation by itself will be enough.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda