2012年6月15日金曜日

C++のエンディアン判定と定数式最適化

configureとか使わずに、コンパイル時にプラットフォームのエンディアンを判定したい。マルチバイトの1の先頭バイトを見るのは、エンディアン判定の常套手段だが、この1を定数にしたら、静的に判定してくれないだろうかと、以下のコードで試してみた。

#include <iostream>
using namespace std;

static const union {
    int one;
    char isLittle;
} endian = {1};
static constexpr union {    // C++11
    int one;
    char isLittle;
} endian2 = {1};
static const int endian3 = 1;
static constexpr int endian4 = 1;   // C++11
static const int const_array[] = {0, 1, 0, 2};

int main() {
    if (endian.isLittle)
        cout << "little endian" << endl;
    if (endian2.isLittle)
        cout << "little endian2" << endl;
    if (*(reinterpret_cast<const char *>(&endian3)))
        cout << "little endian3" << endl;
    if (*(reinterpret_cast<const char *>(&endian4)))
        cout << "little endian4" << endl;
    if (const_array[0])
        cout << "[0] is not zero" << endl;
    if (const_array[1])
        cout << "[1] is not zero" << endl;
    if (const_array[2])
        cout << "[2] is not zero" << endl;
    if (const_array[3])
        cout << "[3] is not zero" << endl;
    return 0;
}
結果はコンパイラによりけり。
Ubuntu 12.04(x86/AMD64)のGCC 4.6.3だと、-O3を付けても、上記の全てのエンディアン判定で比較と分岐命令を生成してしまった。ただ、エンディアン判定には使えないけれど、const_array[]を使った分岐は最適化によって消滅した。
Mac OS X LionのLLVM GCC 4.2.1とLLVM compiler 3.1だと、-O3を付ければ全ての分岐は消滅してくれた。素晴らしい!

0 件のコメント:

コメントを投稿