質問

Cプログラムは、実行時に(コンパイルされていない)、リトルエンディアンで実行されているか、大エンディアンCPUで実行されているかどうかをどのように決定しますか?

「コンパイル時」ではなく「実行時」チェックでなければならない理由は、Intel CPU を備えた MAC を使用して、MAC OSX のユニバーサル バイナリ フォーマットでプログラムをビルドしているためです。そして、このプログラムは Intel と Power-PC CPU の両方で動作することが期待されています。つまり、MAC 上のユニバーサル バイナリ フォーマットを通じて、Intel CPU を使用してプログラムを構築し、PPC CPU で実行したいと考えています。

私のプログラムで CPU チェックが必要なロジックは、64 ビット整数のホストからネットワークへのバイト順序変更関数です。現在、バイトオーダーを盲目的に交換していますが、Intel CPU では問題なく動作しますが、PPC では動作しません。C 関数は次のとおりです。

unsigned long long
hton64b (const unsigned long long h64bits) {
   // Low-order 32 bits in front, followed by high-order 32 bits.
   return (
       (
        (unsigned long long)
        ( htonl((unsigned long) (h64bits & 0xFFFFFFFF)) )
       ) << 32
      )
      |
      (
       htonl((unsigned long) (((h64bits) >> 32) & 0xFFFFFFFF))
      );
}; // hton64b()

これをクロスプラットフォームで行うより良い方法はありますか?

ありがとう

役に立ちましたか?

解決

  • プリプロセッサマクロがあります テスト可能かどうか ビッグ/リトルエンディアン。例えば
   #ifdef LITTLE_ENDIAN
   do it little endian way
   #else 
   do it big endian way
   #endif.

これはコンパイル時間ですが、脂肪のソースです バイナリは、 各アーキテクチャでは、これは 問題。

  • macosxに sys/endian.h の betoh64() 関数 - もしそうなら、それを使って 正しいことです。
  • 最後のアプローチは、単に 個々のバイトのアンパック ホストにとって賢明ではない方法 エンディアン - あなたが知る必要があるのは、 バイトが入る順序は、 源。

    uint64_t unpack64(uint8_t *src)
    {
       uint64_t val;
    
       val  = (uint64_t)src[0] << 56;
       val |= (uint64_t)src[1] << 48;
       val |= (uint64_t)src[2] << 40;
       val |= (uint64_t)src[3] << 32;
       val |= (uint64_t)src[4] << 24;
       val |= (uint64_t)src[5] << 16;
       val |= (uint64_t)src[6] <<  8;
       val |= (uint64_t)src[7]      ;
    
       return val;
    }
    

他のヒント

チェックを気にしないでください。あなたはネットワークに依存しない値を必要な場所だけ* hton使用。良いデザインで、それはネットワークに依存しない整数を必要とするあなたのプログラムとどんなことがあるの間のインタフェースだけのモジュールに制限する必要があります。

ネットワーク順に既にあるビッグエンディアンのシステムでは、htonは*おそらくマクロなので、それは無料です。リトルエンディアンのシステムでは、とにかくそれを行うために必要としているので、あなたがそれを行う必要があるかどうかをチェックすることはちょうどあなたを減速されます。

あなたは、実行時にシステムのエンディアンを知っておく必要があり、なぜこれが不十分である

場合、あなたはあなたが達成しようとしているもののより良い説明を提供する必要があります。

あなたは、Mac上のユニバーサルバイナリが一度各アーキテクチャのために、複数回コンパイルされていることを実現しますか?私はちょうど(LITTLE_ENDIANのような)gccの定数を使用する....あなたはについてのコンパイル時間が話すとき、あなたがソースを通知するシステムを作る/あなたのconfigureを使用してに言及していることを想像します。

あなたは、実行時にエンディアンをチェックする必要はありません。あなたはユニバーサルバイナリとしてアプリケーションをコンパイルすると、あなたがIntelマシン上で構築している場合でも、適切な定義やマクロで複数回コンパイルされています。実行時には、マッハ・O・ローダーは、あなたのユニバーサルバイナリ(インテルのPowerPCのか、i386ではすなわちPPC)から実行するのに最適なアーキテクチャを選択します。

ユニバーサルバイナリには、複数のアーキテクチャのための1つのバイナリを意味するものではありません。これは、1つのアーキテクチャのための1つのバイナリを含む1つのファットバイナリを意味します。

HTTPを参照してください。詳細についてはを//developer.apple.com/legacy/mac/library/documentation/MacOSX/Conceptual/universal_binary/universal_binary_intro/universal_binary_intro.htmlます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top