gpt4 book ai didi

arrays - 包含带有 'Implicit' 类运算符的动态数组的 Delphi Record 的初始化

转载 作者:行者123 更新时间:2023-12-03 14:34:18 27 4
gpt4 key购买 nike

我试图弄清楚是否可以使用 Delphi 中的“隐式”类运算符来初始化包含动态数组的记录(Berlin 10.1 upd 1)

附加程序产生以下输出:

ci iA r1 r2 r3
1 1 1 1 49694764491115752
2 2 2 2 11570520
3 3 3 3 0
4 4 4 4 0
5 5 5 5 0
  • TRec 是包含我要初始化的动态数组的记录类型。
  • ci是一个整数常量数组。
  • ia 是一个动态整数数组。
  • r1,r2,r3是TRec类型的记录,它们以不同的方式初始化。

正如您从输出中看到的,使用常量的前两个赋值 (r1,r2) 按预期工作。第三个赋值 r3 := iArray 被编译器接受,但结果被破坏。调试器显示 TRec.Implicit 中的 v 值已经错误。

这里出了什么问题?这有可能吗?

program Project5;

{$APPTYPE CONSOLE}

{$R *.res}

type
TRec = record
iArray: array of UInt64;
class operator Implicit(const v: array of UInt64): TRec;
end;

{ TRec }

class operator TRec.Implicit(const v: array of UInt64): TRec;
var
i: integer;
begin
setlength(Result.iArray, Length(v));
for i := 0 to High(v) do
Result.iArray[i] := v[i];
end;

const
ciArray: array [0 .. 4] of UInt64 = (1, 2, 3, 4, 5);

var
i : integer;
iArray : array of UInt64;
r1, r2, r3: TRec;

begin
iArray := [1, 2, 3, 4, 5];

r1 := [1, 2, 3, 4, 5];
r2 := ciArray;
r3 := iArray;

Writeln('ci iA r1 r1 r3');
for I := 0 to High(ciArray) do
Writeln(ciArray[i], ' ', iArray[i], ' ', r1.iArray[i], ' ', r2.iArray[i], ' ', r3.iArray[i]);

readln;

end.

最佳答案

看起来您发现了代码生成器中的一个错误(它也存在于 Win64 编译器中)。我查看了生成的 asm,似乎编译器为运算符重载生成了错误的指令。这就是为什么错误的值最终出现在运算符重载内的数组中。请在质量门户中报告此情况。

为错误结果生成的代码:

Project109.dpr.46: r3 := iArray;
0040B1F2 A1FC044100 mov eax,[$004104fc]
0040B1F7 8945E8 mov [ebp-$18],eax
0040B1FA 837DE800 cmp dword ptr [ebp-$18],$00
0040B1FE 740B jz $0040b20b
0040B200 8B45E8 mov eax,[ebp-$18]
0040B203 83E804 sub eax,$04
0040B206 8B00 mov eax,[eax]
0040B208 8945E8 mov [ebp-$18],eax
0040B20B 8D4DD8 lea ecx,[ebp-$28]
0040B20E 8B55E8 mov edx,[ebp-$18]
0040B211 4A dec edx
0040B212 B8FC044100 mov eax,$004104fc // <-- wrong one
0040B217 E87CF5FFFF call TRec.&op_Implicit

相等方法的代码:

Project109.dpr.47: r3 := TRec.Implicit(iArray);
0040B22F A1FC044100 mov eax,[$004104fc]
0040B234 8945E4 mov [ebp-$1c],eax
0040B237 837DE400 cmp dword ptr [ebp-$1c],$00
0040B23B 740B jz $0040b248
0040B23D 8B45E4 mov eax,[ebp-$1c]
0040B240 83E804 sub eax,$04
0040B243 8B00 mov eax,[eax]
0040B245 8945E4 mov [ebp-$1c],eax
0040B248 8D4DD4 lea ecx,[ebp-$2c]
0040B24B 8B55E4 mov edx,[ebp-$1c]
0040B24E 4A dec edx
0040B24F A1FC044100 mov eax,[$004104fc] // <-- correct one
0040B254 E8CFF5FFFF call TRec.Implicit

但是,您可以通过为参数类型 TArray<UInt64> 的隐式运算符添加另一个重载来避免这种情况。然后还将局部变量声明为该类型,以便编译器选择正确的重载(在本例中不会生成错误代码的重载)。

但请注意,只有当您传递 TArray<UInt64> 类型的变量时,这才有效。当你有任何其他动态时调用错误的 array of UInt64因为 Delphis 严格的类型规则。

更新:此缺陷已在 RSP-16084 中报告。并在 Delphi 10.2 Tokyo 中修复。

关于arrays - 包含带有 'Implicit' 类运算符的动态数组的 Delphi Record 的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39995637/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com