Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient Pointer Handling in Function Parms

As the topic indicates above, I'm wondering if there's a good example of a clean and efficient way to handle pointers as passed in function parms when processing the data sequentially. What I have is something like:

function myfunc(inptr: pointer; inptrsize: longint): boolean;
   var
     inproc: pointer;
     i: integer;
   begin
     inproc := inptr;
     for i := 1 to inptrsize do
       begin
         // do stuff against byte data here.
         inc(longint(inproc), 1);
       end;
   end;

The idea is that instead of finite pieces of data, I want it to be able to process whatever is pushed its way, no matter the size.

Now when it comes to processing the data, I've figured out a couple of ways to do it successfully.

  1. Assign the parm pointers to identical temporary pointers, then use those to access each piece of data, incrementing them to move on. This method is quickest, but not very clean looking with all the pointer increments spread all over the code. (this is what I'm talking about above)
  2. Assign the parm pointers to a pointer representing a big array value and then incremently process that using standard table logic. Much cleaner, but about 500 ms slower than #1.

Is there another way to efficiently handle processing pointers in this way, or is there some method I'm missing that will both be clean and not time inefficient?

like image 957
Glenn1234 Avatar asked Dec 21 '12 21:12

Glenn1234


People also ask

Is pass by reference more efficient?

Pass-by-references is more efficient than pass-by-value, because it does not copy the arguments. The formal parameter is an alias for the argument. When the called function read or write the formal parameter, it is actually read or write the argument itself.

Which is generally more efficient a function that returns an object by reference or a function that returns an object by value?

Returning the object should be used in most cases because of an optimsation called copy elision. However, depending on how your function is intended to be used, it may be better to pass the object by reference.

How do you pass pointer variables as function arguments?

Pass-by-pointer means to pass a pointer argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the variable to which the pointer argument points. When you use pass-by-pointer, a copy of the pointer is passed to the function.

Why is it more efficient to pass a structure by reference than by value?

In pass by reference, no new copy of the variable is made, so overhead of copying is saved. This makes programs efficient especially when passing objects of large structs or classes.


1 Answers

Your code here is basically fine. I would always choose to increment a pointer than cast to a fake array.

But you should not cast to an integer. That is semantically wrong and you'll pay the penalty anytime you compile on a platform that has pointer size different from your integer size. Always use a pointer to an element of the right size. In this case a pointer to byte.

function MyFunc(Data: PByte; Length: Integer): Boolean;
var
  i: Integer;
begin
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

Unless the compiler is having a really bad day, you won't find it easy to get better performing code than this. What's more, I think this style is actually rather clear and easy to understand. Most of the clarity gain comes in avoiding the need to cast. Always strive to remove casts from your code.

If you want to allow any pointer type to be passed then you can write it like this:

function MyFunc(P: Pointer; Length: Integer): Boolean;
var
  i: Integer;
  Data: PByte;
begin
  Data := P;
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

Or if you want to avoid pointers in the interface, then use an untyped const parameter.

function MyFunc(const Buffer; Length: Integer): Boolean;
var
  i: Integer;
  Data: PByte;
begin
  Data := PByte(@Buffer);
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

Use a var parameter if you need to modify the buffer.

like image 56
David Heffernan Avatar answered Sep 24 '22 00:09

David Heffernan