3

C プログラムは、(コンパイル時ではなく) 実行時に、リトル エンディアンまたはビッグ エンディアンのどちらの CPU で実行されているかをどのように判断しますか?

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

CPU チェックを必要とする私のプログラムのロジックは、64 ビット整数のホストからネットワークへのバイト順変更関数です。現在、インテル 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()

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

ありがとう

4

4 に答える 4

2

わざわざチェックしないでください。ネットワークに依存しない値が必要な場合は、どこでも hton* を使用してください。優れた設計では、プログラムとネットワークに依存しない整数を必要とするものとの間のインターフェイスとなるモジュールのみに制限する必要があります。

すでにネットワーク オーダーになっているビッグ エンディアン システムでは、hton* はおそらく単なるマクロなので、無料です。リトル エンディアン システムでは、とにかくそれを行う必要があるため、それを行う必要があるかどうかを確認することは、単に速度を低下させるだけです。

これが不十分な場合は、達成しようとしていることと、実行時にシステムのエンディアンを知る必要がある理由について、より適切な説明を提供する必要があります。

于 2009-12-02T17:29:52.990 に答える
1
  • ビッグ/リトル エンディアンかどうかをテストするために利用できるプリプロセッサ マクロがあります。例えば
   #ifdef LITTLE_ENDIAN
   リトルエンディアンの方法でそれを行う
   #そうしないと
   ビッグエンディアンでやる
   #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;
    }
    
于 2009-12-02T18:54:04.693 に答える
0

実行時にエンディアンをチェックする必要はありません。アプリケーションをユニバーサル バイナリとしてコンパイルすると、Intel マシンでビルドしている場合でも、適切な定義とマクロを使用して複数回コンパイルされます。実行時に、mach-o ローダーは、ユニバーサル バイナリ (つまり、PowerPC では ppc、Intel では i386) から実行するのに最適なアーキテクチャを選択します。

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

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

于 2009-12-03T10:30:42.397 に答える
0

Mac 上のユニバーサル バイナリは、アーキテクチャごとに 1 回ずつ、複数回コンパイルされることをご存知ですか? コンパイル時間について話すとき、configure/makeシステムを使用してソースに通知することを指していると思います.... gcc定数( LITTLE_ENDIAN など)を使用してください

于 2009-12-02T17:19:52.260 に答える