Mike
Mike

Reputation: 29

Converting an byte array into 2 unsigned long in C and Delphi

The following C code:

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

What is the significance of +sizeof(unsigned long)-4?

Could the memcpy statements be written as:

memcpy((byte *)&iONE, temp, 4);
memcpy((byte *)&iTWO, temp+4, 4);

And is the Delphi conversion valid:

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;

Upvotes: 0

Views: 324

Answers (2)

David Heffernan
David Heffernan

Reputation: 612904

(byte *)&iONE)+sizeof(unsigned long)-4

is trying read 4 bytes from iONE but also account for the possibility that unsigned long is larger than 4 bytes. The code does so by picking off the last 4 bytes of iONE. Since the code always reads from the same end of the variable its behaviour varies between little and big endian machines. Without any context it is hard to say what this code is trying to achieve but my guess is that it was originally running on a big endian system with 8 byte unsigned long. Perhaps you know more.

In Delphi you'd probably write it like this.

var
  temp: array[0..7] of Byte;
  iONE: Cardinal;
  iTWO: Cardinal;
begin
  temp := ...;
  iONE := PCardinal(@temp[0])^;
  iTWO := PCardinal(@temp[4])^;;
end;

However, it would help to know more about the original code. Personally if I was faced with this task I'd write the code from scratch rather than make a literal port. The original code already looks poor and once it has been translated it will be even worse. Work out what the code does and write a new program using the idiom of the target language.

Two minor points on your code:

  1. It is pointless to initialise a variable that is immediately over-written. That just confuses the future reader.
  2. CopyMemory is a Windows API function and as such not portable. System.Move is the function to use for raw memory copies.

Upvotes: 1

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

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

is copying 4 bytes from temp into iONE's address at offset sizeof(unsigned long)-4, and

memcpy((byte *)&iONE, temp, 4);

will copy 4 bytes from temp at the beginning of the address where iONE is stored.

So sizeof(unsigned long)-4 is just an offset in bytes, at which to copy the 4 bytes from temp.

Upvotes: 0

Related Questions