在for循环中一个奇怪的问题?(100分)

  • 主题发起人 经典音乐
  • 开始时间
T

Titita

Unregistered / Unconfirmed
GUEST, unregistred user!
这个是delphi编译器的优化.
如果循环变量在循环体用没有被引用,或者循环体的改变对程序的逻辑没有影响的话,
编译器会自动用最佳的方式来处理循环变量,以达到速度/时间优化的目的.
有时编译器还会自动展开循环呢!;)
 
R

real_clq

Unregistered / Unconfirmed
GUEST, unregistred user!
源码呢?
 

蛐蛐

Unregistered / Unconfirmed
GUEST, unregistred user!
我没有注意过。
 
F

form2

Unregistered / Unconfirmed
GUEST, unregistred user!
真的有啦!只怪各位for用的少,感觉在里面单步跟踪变量好无聊,而造成的
这种东东存在,可遇不可求,包括用公用变量做for变量我也碰过
 
X

xiao_min

Unregistered / Unconfirmed
GUEST, unregistred user!
HOHO,果然是这样:
var
i:integer;
begin
for i:=1 to 10 do
begin
caption:=inttostr(i);
caption:=timetostr(now);
end;
end;
这其中: caption:=inttostr(i);
这句不加的时候,就是从10开始,加上它,就是从1开始
 
S

savenight

Unregistered / Unconfirmed
GUEST, unregistred user!
Titita:请问你的话是在哪里查到的?
 

方栩

Unregistered / Unconfirmed
GUEST, unregistred user!
没错,千真万确有这种错误,只是出现频率极其低,
我也懒得去管,因为肯定是delphi的问题,
每次直接舍弃for循环,换成在repeat循环中累加就OK了。
 

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题不是到宝蓝公司的BBS上提提呀,问问怎么回事,我想这种问题肯定有解释的。
 
Z

zswenyun

Unregistered / Unconfirmed
GUEST, unregistred user!
我也碰到过,本来以为是优化编译的缘故,但是关掉优化编译在单步调试还是出现,但由于
不影响程序,后来也没深究。
〉》经典音乐好样的,不放过任何一个问题。
 
D

DarwinZhang

Unregistered / Unconfirmed
GUEST, unregistred user!
上面有些地方有偏差,改正了一下。
 
D

DarwinZhang

Unregistered / Unconfirmed
GUEST, unregistred user!
我的实验:
var
i,j:Integer;
....
程序一:
j:=0;
for i:=0 to 10 do inc(j);
caption:=IntToStr(j);
程序二:
j:=0;
for i:=7 to 17 do inc(j);
caption:=IntToStr(j);

这两个程序的最后代码是完全相同的,循环部分汇编程序:
.....
mov eax $B //循环次数
inc ebx
dec eax //1
jnz -$4 //2
12两句控制循环结束

程序三:
j:=0;
for i:=10 downto 0 do inc(j);
caption:=IntToStr(j);
.....
mov eax $FFFFFFF5 //设定循环次数,用减法
inc ebx
inc eax //1
jnz -$4 //2
12两句控制循环结束

因为i只是起到一个计数器的作用,其他地方用不到i,所以可以用高效的实现方法。
显然,这段代码是非常高效的,且结果完全符合设计要求。
Delphi在编译时将to语句变成用 dec 来实现,而downto变成用 inc 来实现,
为什么会这样,可能只有Borland的开发小组能说清了,
也许是为了加快编译速度的需要。

程序四:
j:=0;
for i:=0 to 10 do
begin
inc(j);
caption:=IntToStr(i);
end;
caption:=IntToStr(j)

这时候的最后代码发生了变化,循环部分汇编程序如下:
mov ebx,$7
inc edi
...//实现caption:=IntToStr(i);
inc ebx //1
cmp ebx,$12 //2
jnz -$1B //3; 123三句控制循环结束
因为用到了i,所以这一次不会对改变原来的结构。

另外,实验一下下面的代码:
j:=0;
for i:=7 to 17 do inc(j);
Caption:=IntToStr(i);
看一下编译时产生的信息就会不难理解 for 语句的实现方法了。


 

微软第一美女

Unregistered / Unconfirmed
GUEST, unregistred user!
H

hongfei

Unregistered / Unconfirmed
GUEST, unregistred user!
竟然如此有趣!
 
Z

zhumoo

Unregistered / Unconfirmed
GUEST, unregistred user!
这是delphi编译器优化了才会这样子的.一点都不会影响结果. 你在IDE中将优化的选项去掉,再跟踪就正常了.
 

微软第一美女

Unregistered / Unconfirmed
GUEST, unregistred user!

叮叮当当

Unregistered / Unconfirmed
GUEST, unregistred user!
DarwinZhang分析得很有道理。结果也令人信服。
 
C

czl007

Unregistered / Unconfirmed
GUEST, unregistred user!
果然如此,其实你编程时最好不要使用一些可能引起歧义的保留字,好么?这会对你很有帮助!!!
[:)]
 
L

lynu

Unregistered / Unconfirmed
GUEST, unregistred user!
我在delphi6曾经碰到这样的事

str:='';
for i:=0 to 5 do
begin
str:=str+ADOQuery1.FieldByName('StrField'+IntToStr(i)).AsString;
// showMessage(intToStr(i));
// if i>5 then break;
end;
如果没加上if i>5 then break;
最后输出到了10.出现了非法访问才停止
这种情况只在特定的时候才发生.害得我怕用delphi的for了
(我当时根本不相信,找了几个同事来验证,在那一段代码中
build了好几遍,的确如此)
用while就从没有这种问题,但有时又麻烦了一点.
 

萧月禾

Unregistered / Unconfirmed
GUEST, unregistred user!
你用a,b这样的字母代替i好象就没事。。。
 
T

t365

Unregistered / Unconfirmed
GUEST, unregistred user!
这正是delphi编译器的优化结果
不会影响你的结果
但为什么要这样优化
我也不清楚
 
顶部