2016-07-27 3 views
13

構造体がコンパイル時にチェックされているかどうかは、整列が整っているかギャップがあるかどうかです。 チェックは追加のテストコードで行うことができますが、私は実際の実装コードに "パックされた"データを入れたくありません。 構造体が整列しているかギャップがあることをC++で確認してください

これはガード含む典型的な例とヘッダーファイル(MyData.h)である:私は1つの可能な解決策を見つけた

#ifndef MYDATA_H_ 
#define MYDATA_H_ 

struct uneven 
{ 
    int bla_u32; 
    short bla_u16; 
    char bla_u8; 
    /* <-- this gap will be filled in the unpacked version */ 
}; 

#endif // MYDATA_H 

を - 下記参照。

質問:

  • 構造体unevenは時間をコンパイルでそのアンパック対応物と比較バイトの異なる数が含まれているかどうかを確認するためにエレガントな方法はありますか?

  • C(ネームスペースを使用しないで)で動作する解決策がありますか?

+1

追加のテストコードでチェックが行われる可能性はありますか?アサーションをコード内に置くことをコントロールしたいですか? そうでなければ、コンパイル時にチェックしたい新しい構造体の静的なアサーション実装と組み合わせた関数(@Dutowの示唆に似ています)を定義することができます。 – jcxz

+0

"追加のテストコードでチェックが行われる可能性があります"とは、リリース(リリース)コードベースまたは実際の製品の一部ではない追加のcまたはcppファイルでチェック(静的なアサート)または実際のリリースに含まれてはならないもの) –

答えて

3

かわりに、名前空間(on ideone)の機能を使用することができます。

このソリューションはまた、C

ヘッダーファイルで動作します:

typedef struct 
{ 
    int bla_u32; 
    short bla_u16; 
    char bla_u8; 

    /* <-- this gap will be filled in the unpacked version */ 
} uneven; 

ソースファイル:

#include "MyData.h" 

#define StaticAssert(cond, msg) switch(0){case 0:case cond:;} 

void checkSizes() 
{ 
    uneven unpacked_uneven; 
#pragma pack(push, 1) 
    #undef MYDATA_H_ // force re-including "MyData.h" 
    #include "MyData.h" 
#pragma pack(pop) 
    uneven packed_uneven; 
    StaticAssert(sizeof(unpacked_uneven) == sizeof(packed_uneven), "uneven contains gaps"); 
} 

StaticAssertをコンパイル用の関数に入れることができます時間エラー。

+0

Dutowのソリューションを私のサンプルコードとマッチさせました - これはかなりハックだと思いますが、コンパイラの警告でない場合はこの一般的な解決策を考えています-Wpadded ([リンク](http://stackoverflow.com/a/38613971/2056545)を参照) –

2

私はこのStaticAssertマクロは与えられた不均一な構造体のデータに失敗しただけC++で動作する問題の1(何とか意地の悪いと非常にトリッキーな)解決策を見つけ、ないC.

#define StaticAssert(cond, msg) switch(0){case 0:case cond:;} 

#pragma pack(push, 1) 
namespace packed 
{ 
#include "MyData.h" 
} 
#pragma pack(pop) 

#undef MYDATA_H_ // force re-including "MyData.h" 
#include "MyData.h" 

void checkSizes() 
{ 
    StaticAssert(sizeof(packed::uneven) == sizeof(uneven), "uneven contains gaps"); 
} 

- としてパックされたバージョンのサイズは7バイトで、アンパックされた(通常の)バージョンは8バイトです。構造体の最後に追加のcharが追加された場合、テストは成功します。両方のバージョンは8バイトを持ちます。

+0

ネストされた構造体を使用することによってネームスペースを避けることができます。 – Dutow

+0

構造体がCのスコープを持たないので、Cの互換性に役立たない@Dutow – user2079303

+1

または、#define uneven packed_uneven #include "MyData.h" #undef uneven'。 – MSalters

4

CとC++の両方で動作するコンパイラ固有のソリューション:GCCには警告のオプション-Wpaddedがあり、アライメントのためにサイズが変わるすべての定義に対して警告が生成されます。

+0

これは素晴らしく、ずっと簡単です! :) - 残念ながら、それはgcc固有です。代わり-Wpaddedの直接メイクファイルでIは 'の#pragma GCC診断push'構造体と 'の#pragma GCC診断エラー「-Wpadded」 ' ....コードを使用する(システムのチェックを含む防ぐため) '#pragma GCC diagnostic pop' –

関連する問題