max()マクロの解釈
id:selvaggio:20060403が紹介していたコードを解釈してみる。
#define max(T) (((T)(-1)<0)?(((unsigned long long)(-1)>>(65-sizeof(T)*8))):((T)((unsigned long long)(-1))) )
T型で表現できる最大値を返す。
T型とは、[signed | unsigned][char | short | int | long | long long]
のこと。
まず、大量の括弧は演算子の優先度によって、マクロの意味がかわらないための工夫だから無視していいだろう。
あと、三項演算子(?:)はみづらいから、if文っぽく書き換えてみる。
if((T)(-1)<0){ (unsigned long long)(-1) >> (65-sizeof(T)*8); }else{ (T)(unsigned long long)(-1); }
まず、最初の条件分岐、(T)(-1) < 0 というのは、0xFFF...FFFが負の数と解釈されるかどうか、つまりunsignedなのかsignedなのかを調べている。
簡単だから、さきにunsignedなelse節を考える。この場合、0xFFF...FFFがそのまま最大値になるので、0xFFF...FFFを目的の型にキャストする。
最後に、signedな場合を考えてみる。これは、0xFFFF FFFF FFFF FFFF(-1)をキャストして、0x0FF...FFFのように最上位ビットが0な数字を作っている。
例えば、Tがlong longの場合で考えてみる。long longは8バイト(64ビット)なので、0x0FFF FFFF FFFF FFFFを作りたい。このためには0xFFFF FFFF FFFF FFFFを1個右にシフトすればいい。だから、65-sizeof(long long)*8で1という数字を求めている。
で、思ったんだけど、65という数字はlong longが8バイトであることに依存しているから、sizeof(long long)で書き換えたほうが移植しやすいんでない?
#define MAX_SIZE (sizeof(long long)+1) #define max(T) (((T)(-1)<0)?(((unsigned long long)(-1)>>(MAX_SIZE-sizeof(T)*8))):((T)((unsigned long long)(-1))) )