3

マシンのエンディアンを判断するためにマクロを検索しましたが、これに対応する標準のプロプロセッサ マクロは見つかりませんでしたが、多くのソリューションが実行時にそれを実行しています。実行時にエンディアンを検出する必要があるのはなぜですか?

私がそのようなことをしたら:

#ifdef LITTLE_ENDIAN
  inline int swap(int& x) {
    // do swap anyhow
    return swapped;
  }
#elif BIG_ENDIAN
  inline int& swap(int& x) { return x; }
#else
  #error "some blabla"
#endif

int main() {
  int x = 0x1234;
  int y = swap(x);

  return 0;
}

コンパイラは 1 つの関数のみを生成します。

しかし、私がそれを好きなら(predef.endianを参照):

enum {
  ENDIAN_UNKNOWN,
  ENDIAN_BIG,
  ENDIAN_LITTLE,
  ENDIAN_BIG_WORD,   /* Middle-endian, Honeywell 316 style */
  ENDIAN_LITTLE_WORD /* Middle-endian, PDP-11 style */
};

int endianness(void)
{
  uint8_t buffer[4];

  buffer[0] = 0x00;
  buffer[1] = 0x01;
  buffer[2] = 0x02;
  buffer[3] = 0x03;

  switch (*((uint32_t *)buffer)) {
  case 0x00010203: return ENDIAN_BIG;
  case 0x03020100: return ENDIAN_LITTLE;
  case 0x02030001: return ENDIAN_BIG_WORD;
  case 0x01000302: return ENDIAN_LITTLE_WORD;
  default:         return ENDIAN_UNKNOWN;
}


int swap(int& x) {
  switch(endianess()) {
    case ENDIAN_BIG:
      return x;
    break;
    case LITTLE_ENDIAN:
      // do swap
      return swapped;
    break;
    default:
      // error blabla
  }
  // do swap anyhow
}

コンパイラは検出用のコードを生成します。

わからない、なぜ私はこれをしなければならないのですか?

リトル エンディアン マシン用にコンパイルされたコードがある場合、コード全体がリトル エンディアン用に生成され、そのようなコードをビッグ エンディアン マシン (arm wiki:bi-endian のようなバイ エンディアン マシン) で実行しようとすると) コード全体がリトルエンディアン マシン用にコンパイルされます。したがって、int などの他のすべての宣言も le です。

// compiled on little endian
uint32_t 0x1234;  // 0x1234 constant literal
// should result 34120000 on BE
4

3 に答える 3

6

実際には、システムが (現在実行中の) リトル エンディアン モードかビッグ エンディアン モードかをソフトウェアが設定できるシステムがあります。ほとんどのシステムは、特別な状況下での切り替えのみをサポートしており、(システム プログラマなどにとっては幸いなことに) 任意に切り替えることはできません。しかし、実行可能ファイルが、その特定の実行可能ファイルが LE または BE モードで実行されるかどうかを定義することをサポートすることが考えられます。その場合、それがどのOSとプロセッサモデルであるかを選択することに頼ることはできません...

一方、ハードウェアが 1 つのエンディアンのみをサポートしている場合 (たとえば、さまざまな形式の x86)、実行時にチェックする必要はないと思います。リトルエンディアンであることはご存知のとおり、それだけです。どのエンディアンかをチェックするコードをシステムに含めたり、ビッグ エンディアンからリトル エンディアンに変換する変換メソッドを持ち歩いたりするのは (パフォーマンスとコード サイズの点で) 無駄です。

于 2013-04-19T17:25:51.630 に答える
2

実行時にエンディアンを検出する唯一の利点は、マクロをいじる必要がないことだと思います。お気づきのとおり、コードをコンパイルしているマシンのエンディアンを示す標準マクロはありません。そのため、自分で何かを定義してコンパイラに渡すか、アーキテクチャ/を示す他のフラグに応じて条件付きで定義する必要があります。オペレーティングシステム、次のようなもの:

#ifdef _this_system_
#define LITTLE_ENDIAN
#endif
#ifdef _that_system_
#define BIG_ENDIAN
#endif

しかし、考えられるすべてのアーキテクチャに対して何度も繰り返されるため、面倒でエラーが発生しやすくなります。実行時にチェックする方が簡単で安全です。ばかげているように見えますが、実際にはより実用的です。

于 2013-04-19T16:48:18.387 に答える