web-dev-qa-db-ja.com

GCCの__attribute__((__packed__))に相当するVisual C ++

一部のコンパイラには、構造体のパッキング指定子があります。たとえば、::

 RealView ARMコンパイラには「__packed」があります。
 Gnu Cコンパイラには「__attribute__((__packed__))」があります。 「#pragma pack(1)」
のみがあります。

struct定義に入れることができるものが必要です。

情報/ハック/提案? TIA ...

45
Malkocoglu

洗練された方法はわかりませんが、次のような恐ろしいことができます。

#include "packed.h"
struct Foo { /* members go here */ } PACKED;
#include "endpacked.h"

MSVCの場合、packed.h:

#define PACKED
#pragma pack(Push,1)

endpacked.h

#pragma pack(pop)
#undef PACKED

Gccの場合、packed.h:

#define PACKED __attribute__ ((__packed__))

endpacked.h:

#undef PACKED

基本的に、パッキングはプラットフォームに依存しすぎています。パックされた構造体に8ビットのフィールドがあり、16ビットのバイトを持つシステムを考えてみましょう。パックするだけでデータを表す構造体を持つことはできません。2つのシステム間で転送されるときに、8ビットバイトが16ビットバイトに変換される方法を知っている必要があります。 16ビットマシンの構造体にはビットフィールドが必要な場合があります。その場合、実装でどのようにレイアウトされるかを知る必要があります。

そのため、コードを一般的に移植可能にすることを目的としている場合、必要なパック構造をヘッダーファイルのプラットフォーム固有のセクションで定義する必要があります。むしろ、将来の移植が必要に応じてできるようにコードを構成します。

28
Steve Jessop

GNU gccに対してPACKをこのように定義できます

#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))

visual C++の場合は次のようになります。

#define PACK( __Declaration__ ) __pragma( pack(Push, 1) ) __Declaration__ __pragma( pack(pop) )

そして、次のように使用します。

PACK(
struct myStruct
{
    int a;
    int b;
});
72
Steph

私はこの質問が今では古いことを知っていますが、以前に投稿されたものよりも良い解決策があると思います。結局、構造体宣言行のMSVCケースにプラグマを入れることができます。以下を考慮してください。

#ifdef _MSC_VER
#  define PACKED_STRUCT(name) \
    __pragma(pack(Push, 1)) struct name __pragma(pack(pop))
#Elif defined(__GNUC__)
#  define PACKED_STRUCT(name) struct __attribute__((packed)) name
#endif

次に、これは次のように使用できます:

typedef PACKED_STRUCT() { short a; int b } my_struct_t;
PACKED_SRUCT(my_other_struct) { short a; int b };

等.

ここで重要なのは、__ pragmaの使用は、構造体の宣言行の周りでのみ必要なことです。構造体名が指定されている場合はこれを含める必要があります。したがって、名前はマクロのパラメーターになります。もちろん、これは列挙型/クラスに拡張するのは簡単です。これは読者への演習として残しておきます!

パックドキュメントのMSDNページ にあるテストプログラムは、これを確認するのに役立ちます。

[〜#〜] edit [〜#〜]

私のテストでは、WindowsでIntelコンパイラを使用していたことがわかりました。 icl.exeを使用すると、このアプローチは問題なく機能しますが、Microsoftコンパイラー(cl.exe)では機能しません(2010および2013でテスト済み)。

15
Sam Jansen

GCCはVC++パック関連のプラグマをサポートしているため、逆の方法でも実行できます。詳細については、 こちら をご覧ください。

エキス...

Microsoft Windowsコンパイラとの互換性のために、GCCは_#pragma_ディレクティブのセットをサポートします。これらのディレクティブは、構造体(ゼロ幅ビットフィールド以外)、ユニオン、およびその後に定義されるクラスのメンバーの最大アライメントを変更します。以下のn値は常に2のべき乗である必要があり、バイト単位で新しいアライメントを指定します。

#pragma pack(n)は、単に新しい配置を設定するだけです。

#pragma pack()は、コンパイルを開始したときに有効だったアライメントにアライメントを設定します(コマンドラインオプション_-fpack-struct[=<n>]_もコード生成オプションを参照)。

#pragma pack(Push[,n])は、内部スタックに現在のアライメント設定をプッシュし、オプションで新しいアライメントを設定します。

#pragma pack(pop)は、内部スタックの最上部に保存されているものにアライメント設定を復元します(そしてそのスタックエントリを削除します)。

#pragma pack([n])はこの内部スタックに影響しないことに注意してください。したがって、#pragma pack(Push)の後に複数の#pragma pack(n)インスタンスが続き、単一の#pragma pack(pop)でファイナライズされる可能性があります。

いくつかのターゲット、例えばi386およびpowerpcは、文書化された__attribute__((ms_struct))として構造をレイアウトする_ms_struct_ _#pragma_をサポートします。

_#pragma ms_struct on_は、宣言された構造のレイアウトをオンにします。

_#pragma ms_struct off_は、宣言された構造のレイアウトをオフにします。

_#pragma ms_struct reset_はデフォルトのレイアウトに戻ります。

8
Autodidact

サポートするコンパイラに応じて、別の解決策は、少なくともバージョン4.0.4以降、GCCがMicrosoftスタイルのパッキングプラグマをサポートしていることに注意することです(バージョン3.4.6および4.0.4のオンラインドキュメントはgnu.orgで入手できます) -プラグマは前者には記述されておらず、後者にあります)。これにより、構造定義の前に#pragma pack(Push,1)を使用し、定義の後に#pragma pack(pop)を使用するだけで、どちらでもコンパイルできます。

6
Tom

構造体に入れるために何かが必要なのはなぜですか?

#pragma pack(1)は同じだと思うか、何か不足していますか?

あなたはこれを行うことができます:

struct Foo
{
#pragma pack(Push, 1)
int Bar;
#pragma pack(pop)
};

しかし、見苦しい。

2
graham.reeds