アプリ版:「スタンプのみでお礼する」機能のリリースについて

これって、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 どちらも同じ状況です。

A 回答 (3件)

Delphi 7 で試してみましたが、確かになりますね。



詳しいことは分かりませんが、おそらくループカウンタをループ内の処理で使用していないことが原因だと思います。
カウンタをインクリメントしてもデクリメントしても処理結果が変わらないため、コンパイル時の最適化でデクリメントが優先されているのではないでしょうか。

もし、上記の推測が正しいとしたら、対処方法としては以下が考えられます。
(1)ループ内でカウンタを無意味でも使用する
(2)whileを使用する
(3)コンパイル時の最適化を切れるなら切る

ですが、これって別にどちらでも結果に影響はないのでは?
    • good
    • 0
この回答へのお礼

>ループ内でカウンタを無意味でも使用する
で目的とする結果が得られました。

ありがとうございます。

お礼日時:2007/08/09 23:08

最適化の結果というのに一票ですね。



はき出されるアセンブラのソースを見ないと確かなことは言えませんが、このループでは、ルーブの制御変数をカウンタのレジスタに割り振っていると思います。
レジスタにおけるインクリメントとデクリメントの速度差の他に、終了判定時、0でループを抜けるのであれば、比較演算が必要ありません、直前のデクリメントによってゼロフラグが設定されたかでジャンプ命令を実行するだけでよいからです。

x86のアセンブラを忘れているので、ニーモニックは正確ではありませんが例として

加算の場合
LOOP:
inc REG
comp REG,LOOP
jeq EXIT
jmp LOOP
EXIT:

減算の場合
LOOP:
dec REG
jze EXIT
jmp LOOP
EXIT:

のように比較命令が一命令減りますから、ルーブ回数が増えてくると結構効きます

気持ちが悪ければループ変数を使えばいいのででしょうが、実行に影響なければ気にしないのが吉かと
    • good
    • 0
この回答へのお礼

そういえば遠~い昔デクリメントの方が速いって聞いたことがありました。
最適化って良いですね。でも、今回はちょっと困りました。

ありがとうございます。

お礼日時:2007/08/09 23:13

> なぜ、こうなるのか?



ループはインクリメントよりデクリメントの方が速いと言われてます。(差は殆ど無いとの話もありますけど)
変数kはカウンタとして以外使われてないので、最適化された結果では無いかと推測します。

> 対処法はありますか?

逆に何が問題なのでしょうか?
例の処理では問題にならないと思いますけど、、、
    • good
    • 0
この回答へのお礼

サンプルはあくまでも簡単にしたもので・・・・

ありがとうございました

お礼日時:2007/08/09 23:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!