割り算と余りを一度に

Pythonには商と余りを一度に求めるdivmodっていう関数がある。

>>> divmod(10, 3)
(3, 1)

C言語にはないのかなと思って探してみると、やっぱりあった。divって関数だ。

div_t res;
res = div(10, 3);

しかしCRTの実装(VC\crt\src\div.c)を見てみると、

div_t __cdecl div (
  int numer,
  int denom
  )
{
    div_t result;

    result.quot = numer / denom;
    result.rem = numer % denom;

    return result;
}

うわー、思いっきり2回に分けて計算してるしー。

でもね、実際にコンパイルしてみると……

CDQ
IDIV DWORD PTR SS:[EBP+C]

1回にまとめられてる。VCの最適化ってすごいな。

ところで、IDIVの1つ前にCDQが置かれている。こいつが気になった。解説はここにあるが、読んでもよくわからなかった。実際にデバッガで実行してみると、EDX を 0 や F で埋めていたので、どうやら符号拡張に関わる命令らしい。

IDIVの説明によれば、どうも x86 の IDIV は「64ビット割る32ビット」をやるらしく、そのため数字のビット長を拡大する必要があって、それが符号拡張処理ってことか。