printf の評価順序

処理系依存からですが、「処理系依存だけど gcc なら後ろから評価するよ」ということで調べてみました。 もともと awk は C (とはいえ K & R なので随分昔の話) と同じ作者なので、同じ処理系と思いきや、awk では前から評価します。

さて、そもそも以下のコードは前から評価した時と後ろから評価した時で値がどのように変化するのでしょうか。

printf("%d %d %d", i, ++i, i++);

前から評価すると、i の初期値が入っていない場合 awk では 0 になり、++i でインクリメントされた値が入るので、1 となり、次は表示後 (評価後) にインクリメントされるので 1 のままになります。 つまり '0 1 1' になります。

一方で、後ろから評価すると、i の初期値が入っていない状態 (0) を表示した後にインクリメントされますから最後は 0 となり、表示後に 1 になります。 次は 1 をインクリメントしてから表示しますので、2 になり、先頭も 2 になります。 つまり '2 2 0' になります。

これを C で記述すると以下のようになります。

#include <stdio.h>

int main () {
    int i;
    i = 0;
    printf("%d %d %d", i, ++i, i++);
    return 0;
}

gcc でコンパイル後に実行してみると、以下のようになります。

$ ./a.out
2 2 0

確かに後ろから評価されているようです。

次に gawk で処理を行なっています。

$ gawk 'BEGIN {printf("%d %d %d", i, ++i, i++)}'
0 1 1

これは前から評価されていることになります。

nawk でも同じことを試してみます。

$ gawk 'BEGIN {printf("%d %d %d", i, ++i, i++)}'
0 1 1

つまり、gcc は後ろから評価して、awk は前から評価していることになります。