我在使用Delphi中的过程和字符串时遇到了问题.事实是我希望看到输出字符串"1S2S3S4S5S6S",但实际输出是"1234S5S6".在调试过程中,它表示S1,S2,S3和S6字符串变量未初始化(S1,S2,S3,S6为''字符串,S4和S5为值'S').有人可以向我解释一下吗?这是代码:
program StringTest;
{$APPTYPE CONSOLE}
procedure MyProcedure(S1: String; const S2: String; var S3: String;
S4: String; const S5: String; var S6: String;
out S7: String);
begin
S7 := '1' + S1 + '2' + S2 + '3' + S3 + '4' + S4 + '5' + S5 + '6' + S6;
end;
procedure Work;
var
S: String;
begin
S := 'S';
MyProcedure(S, S, S, S, S, S, S);
writeln(S);
end;
begin
Work;
readln;
end.
Run Code Online (Sandbox Code Playgroud)
Rem*_*eau 17
您的S7参数被声明为out参数,因此编译器会在调用函数时将传递的变量设置为空字符串.您正在S为所有参数传递相同的变量,包括输出参数,因此S在函数内部使用参数值之前,将从内存中擦除该值.
进一步详细说明,该过程使用register调用约定,其中S1.. S3分别在CPU寄存器(分别为EAX,EDX和ECX)中传递,而S4.. S6在堆栈中传递.string在将当前值推送到堆栈上S4并且S5(S3并且S6只是指向变量的指针)之后,以及在将值分配给S1和之前,输入变量将被清除S2.所以,S1和S2结束零,S4并S5包含指向原来的'S'擦拭前的数据,S3并S6在指向string的是被歼灭变量.
调试器可以向您显示所有这些操作.如果在MyProcedure()调用的行中放置断点,然后打开CPU视图,您将看到以下汇编指令:
StringTest.dpr.17: MyProcedure(S, S, S, S, S, S, S);
00405A6C 8B45FC mov eax,[ebp-$04] // [ebp-$04] is the current value of S
00405A6F 50 push eax // <-- assign S4
00405A70 8B45FC mov eax,[ebp-$04]
00405A73 50 push eax // <-- assign S5
00405A74 8D45FC lea eax,[ebp-$04]
00405A77 50 push eax // <-- assign S6
00405A78 8D45FC lea eax,[ebp-$04]
00405A7B E8B0EDFFFF call @UStrClr // <-- 'out' wipes out S!
00405A80 50 push eax // <-- assign S7
00405A81 8D4DFC lea ecx,[ebp-$04] // <-- assign S3
00405A84 8B55FC mov edx,[ebp-$04] // <-- assign S2
00405A87 8B45FC mov eax,[ebp-$04] // <-- assign S1
00405A8A E8B9FEFFFF call MyProcedure
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您需要使用另一个变量来接收输出:
procedure Work;
var
S, Res: String;
begin
S := 'S';
Proc(S, S, S, S, S, S, Res);
WriteLn(Res);
end;
Run Code Online (Sandbox Code Playgroud)
或者,将过程更改为String通过其返回new Result而不是使用out参数的函数:
function MyFunction(S1: String; const S2: String; var S3: String;
S4: String; const S5: String; var S6: String): String;
begin
Result := '1' + S1 + '2' + S2 + '3' + S3 + '4' + S4 + '5' + S5 + '6' + S6;
end;
procedure Work;
var
S: String;
begin
S := 'S';
WriteLn(MyFunction(S, S, S, S, S, S));
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
923 次 |
| 最近记录: |