Ваш параметр S7
объявлен как out
параметром, поэтому компилятор установит переданную переменную в пустую строку, когда функция вызывается. Вы передаете ту же переменную S
для всех параметров, включая выходной параметр, поэтому значение S
будет стерто из памяти до того, как значения параметра будут использоваться внутри функции.
для дальнейшей разработки, процедура использует register
соглашение о вызовах, где S1
.. S3
передаются в регистрах процессора (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
Чтобы это исправить, вам нужно использовать другую переменную для получения выходных :
procedure Work;
var
S, Res: String;
begin
S := 'S';
Proc(S, S, S, S, S, S, Res);
WriteLn(Res);
end;
в качестве альтернативы, изменить процедуру в функцию, которая возвращает новый String
через его 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;
Остерегайтесь: когда вы объявляете параметр с 'const', вы сообщаете компилятору, что он не должен ожидать изменения параметра на протяжении всей этой функции. Вы несете ответственность за то, чтобы вы поддержали это обещание; компилятор не может проверить его для вас. В этом случае вы изменяете 'S' через' S7', в то время как требование 'S2' и' S5' не изменится. –