- ベストアンサー
Delphi for文
これって、Delphiのバグですか?特性ですか? procedure TForm1.Button1Click(Sender: TObject); begin test(); end; //-------------------------- procedure TForm1.test(); var k,x:integer; begin paintbox1.Canvas.pen.Color:=clBlack ; x:=0; for k:=1 to 3 do begin paintbox1.Canvas.moveto(x,0); paintbox1.Canvas.lineto(x,paintbox1.Height); x:=x+2; end; end; forループ内にブレークポイントを付けて「k」の値の変化を見ると、3,2,1と逆順になります。 「x:=x+2」を「x:=x+k」に変更すると、1,2,3と普通の順になります。 なぜ、こうなるのか? 対処法はありますか? Delphi Ver6・ターボDelphi どちらも同じ状況です。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
Delphi 7 で試してみましたが、確かになりますね。 詳しいことは分かりませんが、おそらくループカウンタをループ内の処理で使用していないことが原因だと思います。 カウンタをインクリメントしてもデクリメントしても処理結果が変わらないため、コンパイル時の最適化でデクリメントが優先されているのではないでしょうか。 もし、上記の推測が正しいとしたら、対処方法としては以下が考えられます。 (1)ループ内でカウンタを無意味でも使用する (2)whileを使用する (3)コンパイル時の最適化を切れるなら切る ですが、これって別にどちらでも結果に影響はないのでは?
その他の回答 (2)
- ultraCS
- ベストアンサー率44% (3956/8947)
最適化の結果というのに一票ですね。 はき出されるアセンブラのソースを見ないと確かなことは言えませんが、このループでは、ルーブの制御変数をカウンタのレジスタに割り振っていると思います。 レジスタにおけるインクリメントとデクリメントの速度差の他に、終了判定時、0でループを抜けるのであれば、比較演算が必要ありません、直前のデクリメントによってゼロフラグが設定されたかでジャンプ命令を実行するだけでよいからです。 x86のアセンブラを忘れているので、ニーモニックは正確ではありませんが例として 加算の場合 LOOP: inc REG comp REG,LOOP jeq EXIT jmp LOOP EXIT: 減算の場合 LOOP: dec REG jze EXIT jmp LOOP EXIT: のように比較命令が一命令減りますから、ルーブ回数が増えてくると結構効きます 気持ちが悪ければループ変数を使えばいいのででしょうが、実行に影響なければ気にしないのが吉かと
お礼
そういえば遠~い昔デクリメントの方が速いって聞いたことがありました。 最適化って良いですね。でも、今回はちょっと困りました。 ありがとうございます。
- papayuka
- ベストアンサー率45% (1388/3066)
> なぜ、こうなるのか? ループはインクリメントよりデクリメントの方が速いと言われてます。(差は殆ど無いとの話もありますけど) 変数kはカウンタとして以外使われてないので、最適化された結果では無いかと推測します。 > 対処法はありますか? 逆に何が問題なのでしょうか? 例の処理では問題にならないと思いますけど、、、
お礼
サンプルはあくまでも簡単にしたもので・・・・ ありがとうございました
お礼
>ループ内でカウンタを無意味でも使用する で目的とする結果が得られました。 ありがとうございます。