Search code examples
cpadding

Warning for struct padding in Clang


I created the following structure:

typedef struct  s_fct_printf
{
  char          flag;
  void          (*fct)(void*);
}               t_fct_printf;

static const t_fct_printf       flags[] =
{
  { 's', my_putstr_printf },
  //[...]
  { 'b', display_base_2 },
};

But when I compile with clang option -Weverything, I have the following warning:

warning: padding struct 'struct s_fct_printf' with 7 bytes to
      align 'fct' [-Wpadded]

I found the following solution :

typedef struct  s_fct_printf
{
  char          flag;
  void          (*fct)(void*);
  char          pad[7];
}               t_fct_printf;

But it's not solving the problem:

warning: missing field 'pad' initializer [-Wmissing-field-initializers]
    { 'b', display_base_2 },
warning: padding struct 'struct s_fct_printf' with 7 bytes to
          align 'fct' [-Wpadded]

So I tried that:

typedef struct  s_fct_printf
{
  char          flag;
  char          pad[7];
  void          (*fct)(void*);
}               t_fct_printf;

But got the following errors:

warning: incompatible pointer to integer conversion initializing 'char'
      with an expression of type 'void (void *)' [-Wint-conversion]
    { 'b', display_base_2 },
warning: suggest braces around initialization of subobject
      [-Wmissing-braces]
    { 'b', display_base_2 },
warning: missing field 'fct' initializer [-Wmissing-field-initializers]
    { 'b', display_base_2 },
error: initializer element is not a compile-time constant
    { 's', my_putstr_printf },

The last solution I found was that, but I have read it's not optimized since the compilator does not packaging my variables anymore.

typedef struct __atribute__((__packed__))       s_fct_printf
{
  char          flag;
  void          (*fct)(void*);
}                                               t_fct_printf;

Is there a good solution?


Solution

  • typedef struct  s_fct_printf
    {
      char          flag;
      char          pad[7];
      void          (*fct)(void*);
    }               t_fct_printf;
    

    is good for taking care of the padding issue. However, you'll have to change the way you initialize the array.

    Use

    static const t_fct_printf       flags[] =
    {
      { 's', "", my_putstr_printf },
      { 'b', "", display_base_2 },
    };
    

    Otherwise, the compiler tries to initialize the member pad with my_putstr_printf, which is not what you want.

    Update

    You can avoid the hard coded number 7 for the size of pad by using:

    typedef struct  s_fct_printf
    {
      char          flag;
      char          pad[sizeof(void(*)(void))-1];
      void          (*fct)(void*);
    }               t_fct_printf;
    

    Thanks are due to @WeatherVane for the suggestion.