在我用 C# 排他 OR 一个字符数组的地址之后,无法获得与 Delphi 代码相同的结果



参数:inlong = 0,posit = 5,从ascii文件tmpchar {。,stx,nul,nul,nul,nul}

delphi代码

Procedure TForm1.GetLongFromBuf(Var InLong : Longint; Posit : Integer; ZRepB : ZrepBuf);
Var
  TmpPChar     : Array[0..3] Of Char;
  PLong        : ^Longint;
  I            : Byte;
Begin
For I:= 0 To 3 Do
   TmpPChar[I] := ZRepB[Posit+I];
PLong := @TmpPChar;
InLong := PLong^;
End;

输出:tmpchar {'。',#2,#0,#0},plong = 13f54c,inlong = 558

C#代码

unsafe static long GetLongFromBuf(long InLong, int Posit, char[] ZRepB){
 long* Plong;
 char[] TmpPChar = new char[4];
 for (byte i = 0; i < TmpPChar.Length; i++){
    TmpPChar[i] = ZRepB[(Posit-1) + (i)];
 }
 fixed(char* ch = TmpPChar){
  PLong = (long*)&ch;
  InLong ^= (long)PLong;
 }
 return InLong;
}

输出:tmpchar {'。',' u0002',' 0','0'},plong = 0x000000000000b3cc18,inlong = 11783192

看来,您正在使用此Delphi代码,而不真正了解其在做什么。从您的结果来看,我们可以得出结论,您正在使用pre-nicode版本的delphi(即:D2007或更早)。我们还可以猜测,ZrepBuf正在定义一个字节或[ANSI] char数组。然后,该方法的工作原理如下:

For I:= 0 To 3 Do
  TmpPChar[I] := ZRepB[Posit+I];  /* Copy four sequential bytes to TmpPChar array */
PLong := @TmpPChar;               /* Take a pointer to the head of the array */ 
InLong := PLong^;                 /* Dereference the pointer, interpreting as a 32-bit int */

这是将四个字节转换为32位整数的代码。在Delphi中,LongInt类型是32位integer类型的别名,相当于C#中的int类型,而不是long。Delphi代码中没有使用XOR操作员。在PLong^中,^操作员是一个放电操作。

在C#中,您可以完全避免使用unsafe代码,并只需使用BitConverter类执行此转换:

 byte[] b = new byte[4] { 0x2E, 0x02, 0x00, 0x00 }; 
 int result = BitConverter.ToInt32(b, 0);  // result == 558

在这里,我将输入数组定义为byte[],因为C#中的char(在Delphi 2009或较新的中)是存储Unicode字符的16位类型(两个字节)。您正在阅读的数据是ANSI编码 - 我认为您了解如何将文本文件读取到字节数组中。

顺便说一句,在更现代的delphi中,您还可以重写上面的指针代码以使用TEncoding类以与C#中的BitConverter类相似的方式执行此功能。

最新更新