glibc で UINT_MAX が数値リテラルじゃなかった
上の記事はこの辺をいじってて気付いたのだった:
$ echo -e '#include<limits.h>\nUINT_MAX;'|gcc -E - -o -|tail -n3 # 12 "/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h" 2 3 4 # 2 "<stdin>" 2 (2147483647 * 2U + 1U);
UINT_MAX
= 2^32-1 = INT_MAX
(= 2^31-1 = 2147483647) * 2 + 1 ということで,定数伝播を期待したマクロ定義になってるぽいんだけど.アホなパーザがリテラルのsemantic valueをint型で返して,INT_MAX
を超えた値が壊れるのを恐れてるのかな?
そう言えばAutodesk 3ds Maxというモデラーがあって,それを操作するスクリプト言語 "MAXScript" になぜか私は詳しいのだけど,実際MAXScriptのパーザはアホだったな... JavaScriptみたく値に応じて勝手に 32 bit int か float (doubleだっけ? 忘れた) か,「適切に」切り替わるんだが,INT_MIN
相当の値 (-2147483648) をREPLに打ち込むとfloatになって精度が失われてしまう.ところが INT_MIN+1
相当の値をREPLに打ち込むと,これは32 bit int精度で評価されるので,この値に変数 x
を束縛する.その後に x-1
を評価すると,やはりちゃんと32 bit intとして INT_MIN
相当の値が返る.これは想像するに,パーザ(と言うかレクサ)が,例えば -10 を [TOKEN_MINUS, TOKEN_INT(10)]
のように処理していて,ここでlexeme TOKEN_INT
は内部を32 bit intで管理してるんだろうな.まぁ「forループからのbreakはC++の例外で実装してるから速度を期待しないでね(はぁと)」とか書いてあるような言語だったからな...