CodingFirst

C言語、Perl、JavaScript、最近はPythonも。出来上がったものより、プログラムを書くことが好き。あと、スイーツ。

スポンサーサイト

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

coutの<<に関する評価順

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

下記の記事の<<の評価順がそうなると思ってなかったので調べてみた。
とりあえずcoutや関数の引数にインクリメントは使わない方が良さそうという結論。

int count=0;
cout
  <<count++<<" "
  <<count++<<" "
  <<count++<<" "
  <<count++<<endl;

これを実行すると

3 2 1 0

つまるところ最後尾から読んでるんだなー。

http://d.hatena.ne.jp/kurocaffee/20100815/1281808257
これって<<演算子が左結合だから右から評価されないと思ってたので意外でした。
ちょっと基本から確認しなおす。

int a = 1<<2<<3;
cout<<a<<endl; // => 32

(1<<2)<<3 で 32。左から右に結合され、左から評価されてる。

count=1;
int a = count++<<count++<<count++<<count++;
cout<<a<<" "<<count<<endl; // => 8 5

これも左から右に結合し、評価もしてるけど、countの扱いが微妙。
期待の5にはなってる。
式に使う値を1に確定するのはたぶん const int な一時変数を生んでるとおもう。
というのも、元の式は単純に << ではなくて、
operator<< だったじゃないかと気づいてパラメータを思い出したから。

int count=0;
cout.operator<<(count++).operator<<(endl) //(a)
    .operator<<(count++).operator<<(endl) //(b)
    .operator<<(count++).operator<<(endl) //(c)
    .operator<<(count++).operator<<(endl); //(d)
    //=> 3\n2\n1\n0

operatorの引数はconst int&。
ここで&countと確定するのかと思ったけど、
そうではなくてcountを元にした一時変数がつくられる。
後置のインクリメントがあるので。
合ってるかわからないけど、たぶん、一時変数はd->c->b->aの順に作られ、
1個作るたびにインクリメントが起き、
できた一時変数がoperator<<の引数となってるっぽい。
そう考えたのは関数化してみるとわかる。

int sal(const int& l,const int& r){
cout << r << " ";
return l<<r;
}
int main(){
  sal(sal(sal(sal(0,count++),count++),count++),count++); //=> 3 2 1 0
  cout << endl;
  return 0;
}

便宜上0を入れたので計算結果がゼロになってしまうのがいまいち。
だけど、結合、評価、一時変数が作られるだろう話も含めて再現できている。
コンパイラの事はよくわからないけど、
operatorのときも同じような展開がされてるのだろうと考えたわけ。
で、ここで悩ましいのはインクリメントというか関数の引数の評価について。
関数の引数の評価の順番はc/c++とも確か処理系依存。
たまたま試したgccはこの結果から右から評価しているようだけど、
他のコンパイラでは違う結果になる可能性がある。
とすると、operatorの方も実装依存の可能性がある。
と手元の資料を調べてみたんだけどそれらしい記述は見つからないので断言できず...

なので、分かったことは、

  • 元の 3 2 1 0 と出るのは処理系依存かも知れないので、過信はしない。
  • 関数、operatorでインクリメントや変数の代入は移植性を下げる可能性があるため、書かないよう心がける。

となんだか曖昧な感じになっちゃた。笑ってごまかそう。アハハ...


«  | HOME |  »

Search

Recent Entries

Foot Print



Categories

Monthly

Recent Comments

Recent Trackbacks

Profile

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。