2016-09-29 10 views
12

このトピックでは、SOで多くの質問を述べましたが、これまでのところ解決策が見つかりませんでした。 1つの自然な解決法がここに言及された:Determining endianness at compile time
しかし、コメントに記載されている関連する問題&は同じ答えです。C++を使用してコンパイル時にプログラムでエンディアンを見つける11

いくつかの変更を加えて、g ++ & clang ++(-std=c++11)で同様の解決策を警告なしにコンパイルできます。

static_assert(sizeof(char) == 1, "sizeof(char) != 1"); 
union U1 
{ 
    int i; 
    char c[sizeof(int)]; 
}; 
union U2 
{ 
    char c[sizeof(int)]; 
    int i; 
}; 

constexpr U1 u1 = {1}; 
constexpr U2 u2 = {{1}}; 
constexpr bool IsLittleEndian() 
{ 
    return u1.i == u2.c[0]; // ignore different type comparison 
} 

static_assert(IsLittleEndian(), "The machine is BIG endian"); 

Demo

これは、エンディアンを決定する決定的な方法と見なすことができますか?それとも、タイプ・パンニングなどがありませんか?

+2

'uint8_t(u2.i)'はどちらのエンディアンでも同じ値を生成しませんか?キャストは、最初のバイトを選択するだけでなく、値を保持する必要があります。 –

+1

4バイトの整数には、24の可能なバイト順序があります。実際のコンピュータでは少なくとも3つ以上が使用されています。また、[['' un'] 'signed''' char'に与えられた厳密なエイリアシング規則の例外が 'uint8_t'に適用されることは完全にはっきりしていません。 –

+0

@BoPersson、私は "異なるサイズのタイプの比較"に関するコンパイラの警告を避けたかったのです(私はQ!で主張しようとしています)。ここからは、最小の型で1が表現されますが、型キャストでは許容されることがわかりました。それとも私はあなたの心配を誤解しましたか?私は少しコードを変更します。 – iammilind

答えて

1

あなたの試みは、この明らかに1を非稼働(IsLittleEndian()trueと同一である)と違いはありません:私はC++ 11は、プログラム的のエンディアンを決定するための手段を提供していないと信じてい

constexpr char c[sizeof(int)] = {1}; 
constexpr int i = {1}; 
constexpr bool IsLittleEndian() 
{ 
    return i == c[0]; // ignore different type comparison 
} 

static_assert(IsLittleEndian(), "The machine is BIG endian"); 

コンパイル時にターゲットプラットフォーム。

const uint32_t i = 0xffff0000; 

bool isLittleEndian() { 
    return 0 == *reinterpret_cast<const unsigned char*>(&i); 
} 

C++ 11:私の引数は、実行中にそのチェックを実行するための唯一の有効な方法はunsigned charポインタを(タイプpunningの他の方法は、必然的に未定義の動作が含まれているため)を使用してint変数を調べることであるということですこの関数をconstexprにすることはできません。したがって、このチェックはコンパイル時には実行できません。

+0

試行されたソリューションが機能しない理由をより詳しく説明できますか?または、答えの最初にあなたが言及したもの(非機能)と同じ理由は何ですか。私はビッグエンディアンマシンをチェックする機会はありませんでしたが、あなたが言ったことは真実だと思います。しかし、問題はなぜですか? – iammilind

+0

@iammilindあなたの「解決策」において組合はどのような目的を果たしていますか?あなたは 'U1 :: c'にアクセス/使用することは決してなく、あなたは決して' U2 :: i'にアクセス/使用しません。したがって、それらを削除した後、私は私のバージョンに到着します。 – Leon

+0

2つの共用体はコンパイラーのエラーを排除するだけです。それ以外の場合は1つの共用体になります。あなたが 'u1.i == u1.c [0]'( 'u2'と同じ)をチェックするとうまく動作します。このソリューションは、他にも多くの答えがあります。しかし、それらは実行時に限られています。 'constexpr'の制限のため、コンパイル時には動作しません。ここで、U1とU2は、互いに鏡として機能します。私はコンパイル時にコンパイラを許可するようにトリックしようとしました。それは間違っているかもしれません。しかし、誰かがビッグエンディアンでそれをチェックすればよい。 – iammilind

関連する問題