Given the following:
LBytes: TBytes;
LArr: array[1..512] of Byte;
...
SetLength(LBytes, 512);
What is the correct Move() call to copy all bytes from LBytes to LArr?
Move(LBytes[0], LArr, Length(LBytes)); // works
Move(LBytes[0], LArr[1], Length(LBytes)); // works, too
Move(LBytes, LArr[1], Length(LBytes)); // fail
Can someone explain why it makes no difference between using Larr and Larr[1] but makes a difference between LBytes[0] and LBytes?
Can someone explain why it makes no difference between using Larr and Larr1 but makes a difference between LBytes[0] and LBytes?
That's because LBytes
is a dynamic array which is, ultimately, a pointer to the array. On the other hand, LArr
is the array.
Another way to say this is that dynamic arrays are reference types, and fixed length arrays are value types.
In my book, there are two viable ways to do this:
Assert(Length(LBytes)<=Length(LArr));
Move(LBytes[0], LArr, Length(LBytes));
or
Assert(Length(LBytes)<=Length(LArr));
Move(Pointer(LBytes)^, LArr, Length(LBytes));
I prefer the latter, because it is resilient to a zero length array when range checking is enabled. In that scenario, the first block of code leads to a run time range check error.
You might also be motivated to avoid such low-level trickery. I have a utility class that allows me to write:
TArray.Move<Byte>(LBytes, LArr);
The signature of the method is:
class procedure Move<T>(const Source: array of T; var Dest: array of T); overload; static;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With