2016-11-17 109 views
0

結構填充我創建了以下結構:警告在鏘

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

最後的解決方案,我發現了這一點,但我已閱讀,因爲compilator確實它不是最優化不再打包我的變量。

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

有沒有很好的解決方案?

+2

你沒有說明問題... –

+0

嗯,我的問題是,當我用鏗鏘編譯時,我有這樣的警告:padding struct'struct s_fct_printf'with 7 bytes to 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,這是不是你想要的。

更新

您可以通過使用避免的pad大小的硬編碼數7

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,優秀的建議。 –

+0

但是爲什麼要填補呢?編譯器已經做到了。編譯器只是通知你它填充。 –

0

看來你是在64位系統上運行。 A char需要一個字節,編譯器希望讓函數指針在字64的邊界上開始。因此,它需要在char之後填充7個字節以便對函數指針進行整理。

似乎編譯器只是通知你,但你沒有錯誤。

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) 

我希望你的編譯器有一個類似的機制。