在C和Delphi中将字节数组转换为2个unsigned long

时间:2015-01-25 00:44:27

标签: c 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;

2 个答案:

答案 0 :(得分:1)

(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. 初始化一个立即覆盖的变量是没有意义的。这只会让未来的读者感到困惑。
  2. CopyMemory是Windows API函数,因此不可移植。 System.Move是用于原始内存副本的函数。

答案 1 :(得分:0)

memcpy(((byte *)&iONE)+sizeof(unsigned long)-4, temp, 4);

temp的4个字节复制到偏移iONE的{​​{1}}地址,

sizeof(unsigned long)-4

将从memcpy((byte *)&iONE, temp, 4); 处复制4个字节,该地址位于存储temp的地址的开头。

所以iONE只是一个以字节为单位的偏移量,可以从sizeof(unsigned long)-4复制4个字节。