tags:

views:

138

answers:

2

Hello,

This is my function:

class function TCelebrity.ReadArray<T>(length:integer): byte;
var b:pointer;
begin
  b := @Result;
  if IndexR + SizeOf(T) * length > High(DataRead) + 1 then
    raise Exception.Create('error');
  Move(DataRead[IndexR],b,SizeOf(T) * length);
  Inc(IndexR,SizeOf(T) * length);
end;

IndexR is an integer,DataRead is an array of byte.

The function reads length from DataRead at IndexR(position). In my case it reads 4 bytes at position 0.

The problem is that I'd like to call the function like that:

ar[5] := c.ReadArray<byte>(4); or - @ar[5] := c.ReadArray<byte>(4); //ar is Byte array

I know I could create a parameter with a pointer to the Byte array,but I'd like to know is it possible to be done that way?

EDIT:

I also tried this function,it changes only the ar[5] and its supposed to change from ar[5] to ar[8].

class function TCelebrity.ReadArray<T>(length:integer): byte;
var b:^byte; i:integer;
begin
  b := @Result;
  for I := 0 to length - 1 do
  begin
    b^ := DataRead[IndexR];
    Inc(IndexR);
    Inc(b);
  end;
end;

The second example should work.If ar[0] is placed at $400000 then ar[1] should be placed at $400001 and so on.This is what my function does,but unfortunately it works only to the first parameter.

+1  A: 

In the first function, if you move to b, you move to the place where the pointer to result is stored (B), not to result (pansichar(b)^)

Also your definition of dataread is ambiguous. "array of byte" can both be a dynamic array (on which high() makes no sense) as an open array (where high() does make sense).

Some parenthesis in expressions also hurt nobody, but I don't know if that is the problem here.

Marco van de Voort
In both cases when I call it,I call it with a static array member.Like ar[4]. Its static,but the size will not be always 4 as it's in this example.
John
+6  A: 

First of all, your declaration specifies that it is only returning a single byte, not an array of bytes and certainly not a pointer to an array. In its current state, you're going to overwrite the stack and crash horribly. You could use an untyped "var" parameter instead of a function result.

class procedure TCelebrity.ReadArray<T>(length:integer; var Result);
var b:pointer;
begin
  b := @Result;
  if IndexR + SizeOf(T) * length > High(DataRead) + 1 then
    raise Exception.Create('error');
  Move(DataRead[IndexR],b^,SizeOf(T) * length);
  Inc(IndexR,SizeOf(T) * length);
end;

Then call it like this:

c.ReadArray<byte>(4, ar[5]);

However, that is still very dangerous. You must ensure that at a given offset in array 'ar' there is enough remaining room for the bytes you intend to write.

Allen Bauer
What I really don't understand in this piece of code is why there is a move to b and not b^? Am I missing that, or is it copy/paste of the original msg?
Marco van de Voort
Yes, that was a copy/paste error. I fixed it. Thanks for catching that.
Allen Bauer