3

一般に、C および C++ 標準は、コンパイラの作成者に多くの自由を与えていることを認識しています。しかし特に、C 構造体メンバーのような POD 型は、構造体定義にリストされているのと同じ順序でメモリに配置する必要があることが保証されます。また、ほとんどのコンパイラは、メンバーの配置を修正できる拡張機能を提供します。したがって、構造体を定義し、そのメンバーの配置を手動で指定するヘッダーがあり、そのヘッダーを使用して異なるコンパイラで 2 つのアプリをコンパイルした場合、一方のアプリが構造体のインスタンスを共有メモリに書き込み、他方のアプリが共有メモリに書き込むことができないはずです。アプリはエラーなしでそれを読むことができますか?

ただし、含まれる型のサイズは、同じアーキテクチャ上の 2 つのコンパイラ間で一貫していると想定しています (共有メモリについて話しているので、既に同じプラットフォームである必要があります)。一部の型 (GCC および MSVC 64 ビットでの long と long long など) ではこれが常に当てはまるとは限りませんが、最近では uint16_t、uint32_t などの型があり、float と double は IEEE 標準で指定されています。

4

5 に答える 5

3

オフセットを含むまったく同じメモリ レイアウトを保証でき、データ型が 2 つのコンパイラ間で同じサイズである限り、はい、これで問題ありません。その時点で、構造体はデータアクセスに関して同一であるためです。

于 2010-01-20T16:39:32.517 に答える
2

はい、確かに。私はこれを何度もやりました。混合コードをコンパイルしてリンクする場合でも、構造体形式のデータをマシン間で送信する場合でも、問題と解決策は同じです。

古き良き時代には、これはMS Cと他のほとんどすべてを統合するときに頻繁に発生しました:Borland Turbo C. DEC VAX C、GreenhillsC。

簡単なのは、さまざまなデータ型のバイト数を一致させることです。たとえば、一方の32ビットコンパイラは、もう一方の16ビットコンパイラshortと同じです。int構造を宣言するための一般的なソースコードは通常は良いことなので、いくつかのポイント宣言が役立ちます。

typedef  signed long     s32;
typedef  signed short    s16;
typedef  signed char     s8;
typedef  unsigned long   u32;
typedef  unsigned short  u16;
typedef  unsigned char   u8;
...

MicrosoftCは最も厄介です。デフォルトでは、メンバーを16ビットアラインメントにパディングし、64ビットコードではさらにパディングします。x86上の他のコンパイラは、メンバーをパディングしません。

struct {
    int   count;
    char  type;
    char  code;
    char  data [100];
} variable;

のオフセットはcodeの次のバイトであるように見えるかもtypeしれませんが、間にパディングバイトが挿入されている可能性があります。修正は通常です

#ifdef _MSC_VER    // if it's any Microsoft compiler
 #pragma pack(1)   // byte align structure members--that is, no padding
#endif

同じことを行うためのコンパイラコマンドラインオプションもあります。

于 2010-01-20T17:54:36.710 に答える
0

実際に可能です。関係するすべてのコンパイラが同じコードから同じデータ構造を生成することを確認する必要があります。これをテストする 1 つの方法は、構造体を作成してバイナリ ファイルに書き込むサンプル プログラムを作成することです。結果のファイルを 16 進エディターで開き、それらが同じであることを確認します。または、構造体を配列にキャストしてuint8_t、個々のバイトを画面にダンプすることもできます。

データ サイズが同じであることを確認する 1 つの方法は、コンパイラ間でサイズが変わる可能性がint16_tある単純な古いデータ型の代わりに (stdint.h から) のようなデータ型を使用するintことです (ただし、これは同じプラットフォームで実行されている 2 つのコンパイラではまれです)。

思ったほど難しくありません。複数のコンパイラで使用できるコンパイル済みのライブラリが多数あります。重要なことは、両方のコンパイラが構造を同等に扱っていることを確認できるテスト プログラムを作成することです。

于 2010-01-20T17:40:36.170 に答える
0

コンパイラー 1 によってコンパイルされたライブラリー 1 の構造体を、コンパイラー 2 によってコンパイルされたライブラリー 2 で使用する必要がある場合は、データ型のサイズに加えて、メモリーの配置方法が重要です。

于 2010-01-20T16:51:24.083 に答える
0

コンパイラのマニュアルを参照してください。

ほとんどのコンパイラは、メンバーのアラインメントを修正できる拡張機能を提供します

これらのコンパイラと相互に互換性のある#pragma alignスタイルに制限していますか? その場合、安全性は仕様によって決まります。

移植性の#pragma alignために、プラットフォームのすべてのコンパイラの準拠のための「合理的な」標準を提供する可能性のある ABI を捨てて依存する方がよいでしょう。

C および C++ 標準では決定論的な構造体レイアウト方法論が許可されているため、それらは本質的に無関係です。

于 2010-04-15T00:05:29.920 に答える