在 C# 中对 char 数组的地址进行异或后,无法获得与 Delphi 代码相同的结果
Can't get the same result as the Delphi code, after I exclusive-OR an address of a char array in C#
参数:InLong = 0,Posit = 5,来自 ASCII 文件 TmPChar{.,STX,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 = 0x0000000000b3cc18,InLong = 11783192
看来您在使用这段 Delphi 代码时并未真正理解它的作用。根据您的结果,我们可以得出结论,您使用的是 Delphi 的 pre-unicode 版本(即: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
class:
执行此转换
byte[] b = new byte[4] { 0x2E, 0x02, 0x00, 0x00 };
int result = BitConverter.ToInt32(b, 0); // result == 558
此处我将输入数组定义为 byte[]
,因为 C#(以及 Delphi 2009 或更新版本)中的 char
是 16 位类型(两个字节) 用于存储 Unicode 字符。您正在阅读的数据是 ANSI 编码的 - 我假设您了解如何将文本文件读入字节数组。
顺便说一句,在更现代的 Delphi 中,您还可以重新编写上面的指针代码,以使用 TEncoding
class 以类似的方式执行此功能 通往 C# 中 BitConverter
class 的方式。
参数:InLong = 0,Posit = 5,来自 ASCII 文件 TmPChar{.,STX,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 = 0x0000000000b3cc18,InLong = 11783192
看来您在使用这段 Delphi 代码时并未真正理解它的作用。根据您的结果,我们可以得出结论,您使用的是 Delphi 的 pre-unicode 版本(即: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
class:
byte[] b = new byte[4] { 0x2E, 0x02, 0x00, 0x00 };
int result = BitConverter.ToInt32(b, 0); // result == 558
此处我将输入数组定义为 byte[]
,因为 C#(以及 Delphi 2009 或更新版本)中的 char
是 16 位类型(两个字节) 用于存储 Unicode 字符。您正在阅读的数据是 ANSI 编码的 - 我假设您了解如何将文本文件读入字节数组。
顺便说一句,在更现代的 Delphi 中,您还可以重新编写上面的指针代码,以使用 TEncoding
class 以类似的方式执行此功能 BitConverter
class 的方式。