2016-11-17 11 views
0

Я создал следующую структуру:Предупреждения для заполнения структуры в Clang

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

Но когда я компилирую с лязгом -Weverything, у меня есть следующее предупреждение:

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

Я нашел следующее решение:

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

Но это не решает проблему:

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] 

Так что я пробовал:

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

Но получил следующие ошибки:

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

Последнее решение, которое я обнаружил, что, но я прочитал это не оптимизирована, так как составитель делает не упаковывая мои переменные больше.

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

Есть ли хорошее решение?

+2

Вы не указали проблему ... –

+0

Ну, моя проблема в том, что когда я компилирую с clang, у меня есть это предупреждение: padding struct 'struct s_fct_printf' с 7 байтами до align 'fct' [-Wpadded] – Xwilarg

+0

Это предупреждение можно безопасно игнорировать и подавлять. Структуры заполнения - это совершенно правильная вещь, которую компилятор часто делает. Если вы не полагаетесь на конкретный макет, конечно, что нехорошо делать. –

ответ

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

подходит для ухода за прокладкой. Однако вам придется изменить способ инициализации массива.

Использование

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

В противном случае, компилятор пытается инициализировать член pad с my_putstr_printf, который не то, что вы хотите.

Update

Вы можете избежать трудно закодированный номер 7 для размера pad с помощью:

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

Выражаем благодарность @WeatherVane за предложение.

+0

Я собирался прокомментировать вопрос о том, что предлагаемое дополнение в первом решении OP находится на неправильной стороне функции указатель. Но можно ли вычислить '7' во время компиляции с' sizeof'? –

+0

@WeatherVane, предложение excelleng. –

+0

Но зачем вообще его вставлять? Компилятор делает это уже. Компилятор просто сообщает вам, что он прокладывает. –

0

Кажется, вы запутались в 64-битной системе. A char принимает один байт, и компилятор хочет, чтобы указатель функции начинался с границы слова-64. Следовательно, для привязки указателя функции необходимо добавить 7 байтов после char.

Кажется, компилятор только информирует вас, но вы не ошибаетесь.

2

Я рассмотрел вашу проблему должным образом. Я не чувствую, что добавление поля заполнения - это решение. Он сжимает код и вводит потенциальные будущие проблемы.

Я также понимаю требование качества, что весь код должен компилироваться без предупреждений или ошибок. Однако это предупреждение является только информативным и не указывает на возможную ошибку.

Мой совет будет заключаться в явном подавлении этого предупреждения в тех точках, где он встречается и где происходит принятие.Я бы предложил (используя пример VC):

#pragma warning(disable:4123) 
// The compiler will inform that padding will insert 7 bytes after flag, 
// which will be unused. This is acceptable. 
typedef struct s_fct_printf 
{ 
    char   flag; 
    void   (*fct)(void*); 
}    t_fct_printf; 
#pragma warning(enable:4123) 

Надеюсь, ваш компилятор имеет сопоставимый механизм.

 Смежные вопросы

  • Нет связанных вопросов^_^