【问题标题】:How to translate this portion of C++ code to Delphi [closed]如何将这部分 C++ 代码转换为 Delphi [关闭]
【发布时间】:2021-02-04 00:22:26
【问题描述】:

我试图将 RefPack compression implementation 移植到 Delphi,但我无法理解某些代码部分:

hashtbl = NEW int32[65536];
link    = NEW int32[131072];

hashptr = hashtbl;
for (i=0; i<65536L/16; ++i)
{
    *(hashptr+0)  = *(hashptr+1)  = *(hashptr+2)  = *(hashptr+3) =
    *(hashptr+4)  = *(hashptr+5)  = *(hashptr+6)  = *(hashptr+7) =
    *(hashptr+8)  = *(hashptr+9)  = *(hashptr+10) = *(hashptr+11) =
    *(hashptr+12) = hashptr[13] = hashptr[14] = hashptr[15] = -1L;
    hashptr += 16;
}

这是我的代码:

var
hashtbl: PUInt32;
hashptr: PUInt32;

GetMem(hashtbl, 65536);
GetMem(link, 131072);

hashptr := hashtbl;

for I := 0 to (65536 div 16) - 1 do
begin
    ?!?
    hashptr := hashptr + 16;
end;

问题 1: “65536L” 这个“L”是什么意思?

问题 2: 我不知道循环内的代码是做什么的以及如何将其转录到 Delphi... 有人可以启发我吗?

Ps:我使用的是 Delphi 社区版。

【问题讨论】:

  • 无关:我很难看到 C++ 代码比memset 快​​得多。然后我想多了,思考std::vector&lt;int32&gt; hashtbl(65536, -1);

标签: c++ delphi


【解决方案1】:

在 C++ 中,integer literals 可以包含一个后缀来指定文字的数据类型。在这种情况下,L 后缀代表long。 Delphi 没有这样的后缀,但您可以使用类型化常量。

在 C++ 中,赋值 = 运算符返回对正在赋值的左侧变量的引用。该引用可用于后续表达式。因此,C++ 中的表达式*(hashptr+0) = *(hashptr+1) = ... = hashptr[14] = hashptr[15] = -1L; 表示将-1 分配给hashptr[15],然后将hashptr[15] 分配给hashptr[14],以此类推,直到*(hashptr+1) 分配给*(hashptr+0)。 Delphi 不支持这一点,您必须将这样的表达式拆分为单独的语句。

在 C++ 中,表达式 *(hashptr+N)hashptr[N] 在这种情况下相同。它们都将hashptr 指针增加N 元素,然后取消引用结果以访问被指向的元素。

因此,将所有内容放在一起,C++ 代码只是循环遍历 hashtbl 数组,将每个元素设置为 -1,每次循环迭代 16 个元素。 C++ 代码到 Delphi 的简单字面翻译如下所示:

{$POINTERMATH ON}

var
  hashtbl, link, hashptr: PInt32;
  i: Integer;

...

GetMem(hashtbl, SizeOf(Int32) * 65536);
GetMem(link, SizeOf(Int32) * 131072);

hashptr := hashtbl;

for i := 0 to (65536 div 16)-1 do
begin
  (hashptr+0)^ := -1;
  (hashptr+1)^ := -1;
  (hashptr+2)^ := -1;
  (hashptr+3)^ := -1;
  (hashptr+4)^ := -1;
  (hashptr+5)^ := -1;
  (hashptr+6)^ := -1;
  (hashptr+7)^ := -1;
  (hashptr+8)^ := -1;
  (hashptr+9)^ := -1;
  (hashptr+10)^ := -1;
  (hashptr+11)^ := -1;
  (hashptr+12)^ := -1;
  hashptr[13] := -1;
  hashptr[14] := -1;
  hashptr[15] := -1;
  Inc(hashptr, 16);
end;

...

FreeMem(link);
FreeMem(hashtbl);

这可以大大简化:

var
  hashtbl, link: array of Int32;
  i, j: Integer;

...

SetLength(hashtbl, 65536);
SetLength(link, 131072);

for i := 0 to (65536 div 16)-1 do
begin
  for j := 0 to 15 do begin
    hashtbl[(i*16)+j] := -1;
  end;
end;

...

或者简单地说:

var
  hashtbl, link: array of Int32;
  i, j: Integer;

...

SetLength(hashtbl, 65536);
SetLength(link, 131072);

for i := 0 to 65535 do
begin
  hashtbl[i] := -1;
end;

...

【讨论】:

  • GetMem(hashtbl, SizeOf(Int32) * 65536); GetMem(链接, SizeOf(Int32) * 131072);我习惯于在 Delphi 中使用 PByte,在设置内存分配大小时我什至没有注意到我的错误......它让我很头疼。谢谢。
  • @Delutto 更有理由使用动态数组而不是原始内存,正如我的第二个示例所示。
  • 另外,你确定“(hashptr+0)^ := -1;”吗?我收到错误“E2015 运算符不适用于此操作数类型”
  • @Delutto 是的,我敢肯定,这就是我包含 {$POINTERMATH ON} 以启用该语法的原因,因此它可以匹配 C++ 代码正在执行的操作。
  • 对不起,我错过了。只是为了知识......我正在使用数组,它更“友好”。
【解决方案2】:

L 后缀代表long-1L 是一个 long 常量(或在您的示例中为二进制 32)。

第二部分将hashtbl 数组的每个元素设置为-1。它由 16 个元素组成。

for I := 0 to 65535 do
begin 
  hashtbl[I] := -1;
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2023-03-09
    相关资源
    最近更新 更多