procedure TForm1.FormCreate(Sender: TObject);
var
S: string;
I: Integer;
begin
for I := 1 to 3 do
S := S + IntToStr(I);
ShowMessage(S);
end;
请指出以上代码可能出现的问题。
...全文
134049打赏收藏
[考题]关于局部变量
procedure TForm1.FormCreate(Sender: TObject); var S: string; I: Integer; begin for I := 1 to 3 do S := S + IntToStr(I); ShowMessage(S); end; 请指出以上代码可能出现的问题。
Function XXX : String;
begin
Result := Result + 'ab'
end;
函数等同于
procedure XXX(S : String);
begin
S := S + 'ab'
end;
所以不初始化的话,实际上会使用外部的值,所以要注意。
当遇到不解的问题时,需要查看汇编代码,才能找到到问题的实质。如下:
Function XXX : String;
asm
XOR EAX , EAX
end;
var
S : String;
begin
S := 'aaaa';
S := XXX;
ShowMessage(S); //结果还是 aaaa
end;
上面S的结果还是aaaa是因为XXX函数仅仅把传入的eax值设置为了0,而ShowMessage(S)代码,实际上是一个局部变量的地址[ebp-4],此值并没有变化,所以结果还是aaaa,所以当遇到问题的时候,最终需要查看汇编码来得到答案,大家不要随意下结论。学术要严谨。
返回值类型为 string、动态数组等引用计数管理类型时,实际上是传入隐含参数进行处理。否则如果在栈中使用临时变量的话,由于在函数退出前会对栈中变量进行清理,从而无法正确管理引用计数,导致无法正确实现函数应有的功能。类似的情况,如返回值类型不是很简单的 record 的话,也是采用隐含参数的方式处理的,从而避免在退出函数后仍使用已经失效的栈空间、减少复制变量的开销,各大语言基本上都采用这种方式处理的。
像string,integer等这些32位简单数据类型是通过EAX返回的
像下面的代码就是一句ret返回了,并不做其它的动作(不会改变你的EAX内容)
所以原来的EAX内容是什么还是什么,而使用result、函数名返回、或用var传址方式等,操作的是EAX,所以内容就会改变
Function XXX : String;
begin
end;