在 C 和 Delphi 中将字节数组转换为 2 unsigned long
Converting an byte array into 2 unsigned long in C and Delphi
以下C代码:
typedef unsigned char byte;
byte temp[8] = {...};
unsigned long iONE = 0;
unsigned long iTWO = 0;
memcpy(((byte *)&iONE)+sizeof(unsigned long)-4, temp, 4);
memcpy(((byte *)&iTWO)+sizeof(unsigned long)-4, temp+4, 4);
+sizeof(unsigned long)-4
有什么意义?
memcpy
语句是否可以写成:
memcpy((byte *)&iONE, temp, 4);
memcpy((byte *)&iTWO, temp+4, 4);
Delphi转换是否有效:
var
temp: array[0..7] of Byte;
iONE: Cardinal;
iTWO: Cardinal;
begin
temp := ...;
iONE := 0;
iTWO := 0;
CopyMemory(iOne, temp[0], SizeOf(Cardinal));
CopyMemory(iTwo, temp[4], SizeOf(Cardinal));
end;
memcpy(((byte *)&iONE)+sizeof(unsigned long)-4, temp, 4);
正在将 4 个字节从 temp
复制到 iONE
的偏移量 sizeof(unsigned long)-4
的地址,并且
memcpy((byte *)&iONE, temp, 4);
将从 temp
开始的 4 个字节复制到 iONE
存储地址的开头。
所以sizeof(unsigned long)-4
只是一个字节偏移量,从temp
.
复制4个字节
(byte *)&iONE)+sizeof(unsigned long)-4
正在尝试从 iONE
读取 4 个字节,但也考虑了 unsigned long
大于 4 个字节的可能性。该代码通过选择 iONE
的最后 4 个字节来实现。由于代码总是从变量的同一端读取,因此它的行为在小端和大端机器之间有所不同。在没有任何上下文的情况下,很难说这段代码试图实现什么,但我的猜测是它最初是 运行 在具有 8 字节 unsigned long
的大端系统上。也许你知道的更多。
在Delphi中你可能会这样写。
var
temp: array[0..7] of Byte;
iONE: Cardinal;
iTWO: Cardinal;
begin
temp := ...;
iONE := PCardinal(@temp[0])^;
iTWO := PCardinal(@temp[4])^;;
end;
不过,多了解一下原代码会有所帮助。就我个人而言,如果我面临这项任务,我会从头开始编写代码,而不是进行文字移植。原始代码看起来已经很差了,一旦翻译后会更糟。找出代码的作用并使用目标语言的习语编写新程序。
您的代码有两个小问题:
- 初始化一个立即被覆盖的变量是没有意义的。这只会混淆未来 reader。
CopyMemory
是一个 Windows API 函数,因此不可移植。 System.Move
是用于原始内存副本的函数。
以下C代码:
typedef unsigned char byte;
byte temp[8] = {...};
unsigned long iONE = 0;
unsigned long iTWO = 0;
memcpy(((byte *)&iONE)+sizeof(unsigned long)-4, temp, 4);
memcpy(((byte *)&iTWO)+sizeof(unsigned long)-4, temp+4, 4);
+sizeof(unsigned long)-4
有什么意义?
memcpy
语句是否可以写成:
memcpy((byte *)&iONE, temp, 4);
memcpy((byte *)&iTWO, temp+4, 4);
Delphi转换是否有效:
var
temp: array[0..7] of Byte;
iONE: Cardinal;
iTWO: Cardinal;
begin
temp := ...;
iONE := 0;
iTWO := 0;
CopyMemory(iOne, temp[0], SizeOf(Cardinal));
CopyMemory(iTwo, temp[4], SizeOf(Cardinal));
end;
memcpy(((byte *)&iONE)+sizeof(unsigned long)-4, temp, 4);
正在将 4 个字节从 temp
复制到 iONE
的偏移量 sizeof(unsigned long)-4
的地址,并且
memcpy((byte *)&iONE, temp, 4);
将从 temp
开始的 4 个字节复制到 iONE
存储地址的开头。
所以sizeof(unsigned long)-4
只是一个字节偏移量,从temp
.
(byte *)&iONE)+sizeof(unsigned long)-4
正在尝试从 iONE
读取 4 个字节,但也考虑了 unsigned long
大于 4 个字节的可能性。该代码通过选择 iONE
的最后 4 个字节来实现。由于代码总是从变量的同一端读取,因此它的行为在小端和大端机器之间有所不同。在没有任何上下文的情况下,很难说这段代码试图实现什么,但我的猜测是它最初是 运行 在具有 8 字节 unsigned long
的大端系统上。也许你知道的更多。
在Delphi中你可能会这样写。
var
temp: array[0..7] of Byte;
iONE: Cardinal;
iTWO: Cardinal;
begin
temp := ...;
iONE := PCardinal(@temp[0])^;
iTWO := PCardinal(@temp[4])^;;
end;
不过,多了解一下原代码会有所帮助。就我个人而言,如果我面临这项任务,我会从头开始编写代码,而不是进行文字移植。原始代码看起来已经很差了,一旦翻译后会更糟。找出代码的作用并使用目标语言的习语编写新程序。
您的代码有两个小问题:
- 初始化一个立即被覆盖的变量是没有意义的。这只会混淆未来 reader。
CopyMemory
是一个 Windows API 函数,因此不可移植。System.Move
是用于原始内存副本的函数。