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

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

DarwinZhang

Unregistered / Unconfirmed
GUEST, unregistred user!
如果将“编译优化”去除,得到的结果:
j:=0;
for i:=10 to 17 do inc(j);
caption:=IntToStr(j);
的汇编代码:
....
mov [ebp-$C],$a
inc dword ptr [ebp-$c]
inc dword ptr [ebp-$8]
cmp dword ptr [ebp-$8],$12
jnz -$0c
...
真是惨不忍睹,效率降到了极点,
所以还是不要关掉“编译优化”选项。
另外,如果不关掉“编译优化”选项,
循环变量取任何名称都不会改变编译结果,
至少我在D6/Win2K下的结果是这样。

 
Y

yangxiao_jiang

Unregistered / Unconfirmed
GUEST, unregistred user!
你是从WATCH里看到的吧
我问别人,是编译器优化的问题
好象是没事
 
L

lfpsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
我没有试过,但程序里好多地方都用到过FOR语句,但没有出现问题呀!
 
O

OopsWare

Unregistered / Unconfirmed
GUEST, unregistred user!
问题的确存在,下载下面的代码: 问题出在 Encrpt.pas 单元的第 470 行!
http://oopsware.51.net/other/encrypt.zip
解决的办法有几个,但还是比较烦:
1。给变量i做个强制转换 KeyBuf[k] := (tmp[[red]integer(i)[/red]] shr j) and 1;
2。换 while .
这种错误一般不会出现,所以多数人测试未发现这个错误,但是如果你的单元中
有大量的给大数组赋初值的,问题就出现了,而且delphi的代码编辑器在调试这
些数组时常莫名其妙的出现地址错误,然后delphi自己关闭...
 
G

goodzp

Unregistered / Unconfirmed
GUEST, unregistred user!
晕,楼主该结贴了....
 
9

9903

Unregistered / Unconfirmed
GUEST, unregistred user!
咦?是这样阿,好像只要循环中没有引用到循环变量,编辑器就自动优化成10~1这样的了
 
F

firstrose

Unregistered / Unconfirmed
GUEST, unregistred user!
这是编译器的优化。如果想要正常次序,把优化选项关掉。
 
W

wgjxx

Unregistered / Unconfirmed
GUEST, unregistred user!
建议用While 语句,估计是index的问题,有时不要钻进一个死胡同里经常换一换。
 

胡柚

Unregistered / Unconfirmed
GUEST, unregistred user!
这是编译器对for语句的优化,并不影响执行的结果的,如果在循环体内用到循环变量,则不优化,如果用不到该循环变量,编译器自动按最佳循环方向编译。大家如果想要发现该现象,也只能在单步跟踪的时候发现。
 
M

masm

Unregistered / Unconfirmed
GUEST, unregistred user!
你们都没学过汇编?????
For i:=1 to 100
汇编语言就是
mov ecx,99
aaa:...
dec ecx
jnz aaa
jnz或jz判断跳转语句都是以0或者非0作为条件的(CPU硬件电路所决定),显然,倒序到0判断最高效!!
但如果i要在循环体内引用,那就不得不按照写的顺序来了...
我不是学计算机出身的,但我学过汇编,写过病毒,所以我想我对机器底层、语言底层的感悟比有些科班出身的人还要透彻!别骂我!!
 
L

ljlljl-79

Unregistered / Unconfirmed
GUEST, unregistred user!
Z

zhukewen

Unregistered / Unconfirmed
GUEST, unregistred user!
看看汇编
 
Y

Yves

Unregistered / Unconfirmed
GUEST, unregistred user!
哦???以前没发现
刚看到,觉得masm说得有道理
 
Y

yanghai0437

Unregistered / Unconfirmed
GUEST, unregistred user!
我昨天晚上就碰到了,现在正打算换while算了(我用的是d6/win98)
if ReadChar(0,32,@bCardType)=DC_SUCCESS then
begin
for i:=0 to 15 do //而这里又没有问题
begin
if IC_CARD_COMPCODE<> bCardType then
begin
Result:=IC_COMPANY_CODE_ERROR;
Exit;
end;
end;

j:=0;
for j:=42 to 55 do //这里的j总是不正确。我开始用i,出错了才换成j
begin
if IC_Card_UserCode[j-42]<> bCardType[j] then//导致这里的比较也不正确
begin
Result:=IC_USER_CODE_ERROR;
Exit;
end;
end;

RESULT:= IC_SUCCESS;
end
 
Y

yanghai0437

Unregistered / Unconfirmed
GUEST, unregistred user!
if ReadChar(0,32,@bCardType)=DC_SUCCESS then
begin
for i:=0 to 15 do
begin
j:=i
//加上这句
if IC_CARD_COMPCODE<> bCardType then
begin
Result:=IC_COMPANY_CODE_ERROR;
Exit;
end;
end;

j:=0;
for j:=42 to 55 do //这里的j总是不正确。我开始用i,出错了才换成j
begin
i:=j
//加上这句,然后就没有问题了
if IC_Card_UserCode[j-42]<> bCardType[j] then//导致这里的比较也不正确
begin
Result:=IC_USER_CODE_ERROR;
Exit;
end;
end;

RESULT:= IC_SUCCESS;
end
要在for循环中引用循环变量,有的时候又不用,这下可麻烦了,不知道什么时候需要引用
 
G

guifuli

Unregistered / Unconfirmed
GUEST, unregistred user!
我也碰到过,非常讨厌,一般有这种问题我都用while
 

乖乖兔

Unregistered / Unconfirmed
GUEST, unregistred user!
我也碰到过这样的问题,在调试程序时,设置了断点,
程序停下后,你将鼠标放在 for 的变量上,提示的窗口中数字是从大到小变后的。
如:for s := 1 to 10 do ......
其中将鼠标放到 s 上,提示的数字是从 10 到 1 变。
其实,你看到的这个值不是 s 的值,s 的值是实际是从 1 到 10 变的。
这里,提示窗口中显示的值其实是这个 for 循环剩余的次数,所以会是倒着减少的。
 
G

guifuli

Unregistered / Unconfirmed
GUEST, unregistred user!
to 乖乖兔:
不是吧,这种情况有时才会出现的,象上面Yanghai0437的那段程序,前一个for循环是正确的,而后一个for循环是错误的,为什么呢?如果照你那么说的话,那前一个又错了,这是怎么一回事,你明白吗?
 

猪头堂主

Unregistered / Unconfirmed
GUEST, unregistred user!
我试过了,没遇过这种情况啊,还是把源码帖出来看看吧~
 
G

guifuli

Unregistered / Unconfirmed
GUEST, unregistred user!
源代码如下:

if ReadChar(0,32,@bCardType)=DC_SUCCESS then
begin
for i:=0 to 15 do //而这里又没有问题
begin
if IC_CARD_COMPCODE<> bCardType then
begin
Result:=IC_COMPANY_CODE_ERROR;
Exit;
end;
end;

j:=0;
for j:=42 to 55 do //这里的j总是不正确。我开始用i,出错了才换成j
begin
if IC_Card_UserCode[j-42]<> bCardType[j] then//导致这里的比较也不正确
begin
Result:=IC_USER_CODE_ERROR;
Exit;
end;
end;

RESULT:= IC_SUCCESS;
end

 
顶部