#include <stdio.h> #include <assert.h> static const int _ONE_ = 1 ; // assert() による前提条件のチェック付き isLittleEndianCPU() #define isLittleEndianCPU() (\ assert(sizeof(char) < sizeof(int)),\ *((char*)(&_ONE_)) != 0\ ) // ちなみに、VC++ 6.0 でコンパイル後のコードを調べてみると、 // 前提条件が成り立つなら、チェックにかかる実行時コストは 0 であった。 // // ↑ // // #define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) ) // // と定義されてるので、もともと exp が 0 のときしか // // _assert() が呼ばれないようになってるんだけど、 // // コンパイル時に exp が非0定数だと判定できた場合には、 // // 最適化により _assert() の呼び出しコード自体が削除される。 // // 最後に残る (void)((exp)) も、何ら効果が無い式であり、 // // コンパイル後の コードには現れない。 // // つまり、コンパイル時定数をチェックするための assert() では、 // 実行効率には何のペナルティも生じない。(VC++ 6.0) // // もちろん前提条件が成り立たない/実行時にしか判定できない場合は、 // _assert() 呼び出しのためのコスト (= コード量増大) がかかる int main(void){ if (isLittleEndianCPU()){ printf("Little Endian.\n") ; }else{ printf("Big Endian.\n") ; } return 0 ; } // これはこれでうまく動くのだが…… // // 問題点 : // sizeof(char) < sizeof(int) はコンパイル時に決まる定数にも関わらず、 // 実行時にしかチェックできない。 // つまり、テスト時の網羅度が低いと発見が遅れる可能性がある。 // 前提条件が成り立たない場合、コンパイル時にエラーとして検出できないか? // // 目標 // コンパイル時定数 exp が、 // 0 のとき : コンパイルエラー // 0 以外のとき : 実行時コスト0 (= コンパイル後のコードに現れない) // ような、StaticAssert(exp) を作る。 // [追加条件] // exp が コンパイル時に決まらない変数の場合もコンパイルエラーとなること。