Delphi字节顺序反转

3

我一直在尝试编写一个函数,它接受两个指针(输入和输出),并将输入的字节以相反的顺序写入输出。到目前为止,我还没有能够使它正确工作。

procedure ReverseBytes(Source, Dest: Pointer; Size: Integer);
var
  Index: Integer;
begin
  Move(Pointer(LongInt(Source) + Index)^, Pointer(LongInt(Dest) + (Size - Index))^ , 1);   
end;

请问有没有更好的方法来完成这个任务。

谢谢。


5
我敢打赌你实际上并不想颠倒字节顺序。你可能想要做的是将主机字节顺序转换为网络字节顺序。所有通信库中都有此类函数。使用它们可以使你的代码更加逻辑准确。这就像除以2和右移1之间的区别。当你在大端机器上运行代码时,这还可以避免头痛烦恼。 - David Heffernan
2个回答

7
procedure ReverseBytes(Source, Dest: Pointer; Size: Integer);
begin
  Dest := PByte( NativeUInt(Dest) + Size - 1);
  while (Size > 0) do 
  begin
    PByte(Dest)^ := PByte(Source)^;
    Inc(PByte(Source));
    Dec(PByte(Dest));
    Dec(Size);
  end;
end;

2
+1 明确、快速和高效。另一种更快的模式可能是将字节从两端反转,直到中间。但比其他实现要好得多。 - Arnaud Bouchez

1
procedure ReverseBytes(Source, Dest: Pointer; Size: Integer);
var
  Index: Integer;
begin
  for Index := 0 to Size - 1 do
    Move(Pointer(LongInt(Source) + Index)^, 
        Pointer(LongInt(Dest) + (Size - Index - 1))^ , 1);
end;

procedure TForm2.Button2Click(Sender: TObject);
var
  s: AnsiString;
  P: Pointer;
begin
  s := #0'testreverse';
  GetMem(P, Length(s));
  ReverseBytes(Pointer(s), P, Length(s));

  ShowMessage(PAnsiChar(P));   // esrevertset
  FreeMem(P);
end;

我想知道为什么要调用整个Move例程而不是简单的字节赋值 - 是出于教学目的吗?还有一个小修正 - 对于Delphi的Unicode版本,ShowMessage(PAnsiChar(P))会更好。 - MBo
@MBo - 我的意图是帮助识别原始代码中的问题。感谢您提供 PAnsiChar 的更正。 - Sertac Akyuz
使用大小为1的Move()方法真是太糟糕了!即使原帖作者使用了它,这也不是重点。 - Arnaud Bouchez
@Arnaud - 这正是关键所在。我在你之前的评论中也解释了这一点。有人遇到如此基本的问题,最重要的是他能够确定问题出在哪里。无论如何,感谢您的评论。 - Sertac Akyuz
另一个问题:在这里最好使用64位指针算术,例如使用move(PAnsiChar(Source)[Index],PAnsiChar(Dest)[Size-Index-1],1) - 或者更好的是 PAnsiChar(Dest)[Size-Index-1] := PAnsiChar(Source)[Index] 而不是不兼容的 longint(Source) - Arnaud Bouchez
@Arnaud - 你似乎不理解为什么我在问题中没有尽可能修改原始代码,尽管我如何努力解释。你已经投票了,我对你的微小优化或未来准备不感兴趣,这是我已经说过的原因。但是,如果你认为人们会从你的评论中获得巨大价值,当然可以继续。 - Sertac Akyuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接