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

115
Visualizações
I need a way in a C preprocessor #if to test if a value will create a 0-size array

I have a structure that must pad out to 64K to fit perfectly in an embedded project, so that it fills out a flash block. So there is a #define that adds up the elements in the structure using sizeof() and determines how big the pad[] at the end needs to be to cause the total size to be 64K.

For example :

#define SIZE_OF_MY_PAD (0x10000 - (sizeof(uint16_t) + sizeof(uint8_t)*32 + ... ))

typedef struct {
  uint16_t firstElement;
  uint8_t  secondElementArray[32];
  ...
  uint8_t pad[SIZE_OF_MY_PAD];
};

This has worked great for a long time until suddenly we don't need the pad at all in certain build configurations because it is already exactly 64k. This causes the code to fail because our compiler (not GCC) does not allow pad[0].

I have tried various ways to create a preprocessor value that I can use in an #if statement when this is detected, but it always fails because although sizeof() is legal in #define, it is not legal in #if.

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

0

This problem can be solved without any need for preprocessor with a help of anonymous structs introduced in C11.

Define the flash type as a union that contains members embedded into anonymous struct. Make char _pad[0x10000] the other member of the union to force the total size of the introduced type.

typedef union {
    struct {
        uint16_t firstElement;
        uint8_t  secondElementArray[32];
        float thirdElement;
    };
    char _pad[0x10000];
} flash_t;

This solution is robust to any modifications to the layout of the struct members. Moreover, this avoids problem of defining zero-length array that is technically forbidden by C standard (though allowed in GCC). Additionally, one can add a static assert to check if the maximal size of the flash got overflown.

Example program:

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>

typedef union {
    struct {
        uint16_t firstElement;
        uint8_t  secondElementArray[32];
        float thirdElement;
        // int kaboom[20000]; // will trigger assert if uncommented
    };
    char _pad[0x10000];
} flash_t;

_Static_assert(sizeof(flash_t) == 0x10000, "Oops, flash_t got too large");

int main() {
    flash_t flash;
    printf("offsetof(flash.firstElement) = %zi\n", offsetof(flash_t, firstElement));
    printf("offsetof(flash.secondElementArray) = %zi\n", offsetof(flash_t, secondElementArray));
    printf("offsetof(flash.thirdElement) = %zi\n", offsetof(flash_t, thirdElement));
    printf("sizeof(flash) = %zi\n", sizeof flash);
    return 0;
}

Produces expected output:

offsetof(flash.firstElement) = 0
offsetof(flash.secondElementArray) = 2
offsetof(flash.thirdElement) = 36
sizeof(flash) = 65536

EDIT

  • As suggested in the comment the union member _pad could be renamed to _rawData because semantics of _pad differs from pad in the question.

  • If a member pad within the type is required then one could add it as a flexible member at the end of anonymous struct.

typedef union { struct { ...; uint8_t pad[]; }; char _rawData[0x10000]; } flash_t;
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