在 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;

不过,多了解一下原代码会有所帮助。就我个人而言,如果我面临这项任务,我会从头开始编写代码,而不是进行文字移植。原始代码看起来已经很差了,一旦翻译后会更糟。找出代码的作用并使用目标语言的习语编写新程序。

您的代码有两个小问题:

  1. 初始化一个立即被覆盖的变量是没有意义的。这只会混淆未来 reader。
  2. CopyMemory 是一个 Windows API 函数,因此不可移植。 System.Move 是用于原始内存副本的函数。