* * *

Author Topic: Negative array index via variable, or how to use a pointer as array?  (Read 223 times)

Artlav

  • New member
  • *
  • Posts: 17
    • Orbital Designs
Related to http://mantis.freepascal.org/view.php?id=31554 , since i suspect i'm missing something.

In C, a pointer is an array.
Given byte *p you can access the next byte using b[1], and previous using p[-1].
Trying to port over C code to pascal then very often requires some sort of a way to mimic this functionality.

The closest non-ugly thing i am aware of is defining an infinite array, declaring a pointer to it, and using that pointer instead of a simple pointer.
For example:
Code: Pascal  [Select]
  1. program negative;
  2. type
  3. bytea=array[0..maxint-1]of byte;
  4. pbytea=^bytea;
  5.  
  6. var arr:array[0..10000]of byte;
  7. p:pbytea;
  8. n:integer;
  9.  
  10. begin
  11.  n:=-5;
  12.  p:=@arr[1000];
  13.  arr[1000-5]:=10;
  14.  writeln(p^[n]);    //<--FPC crashes here on x86-64, but works everywhere else
  15. end.

In my case, i wanted to port the machine generated code for FAST corner detector (that is, retarget the code generator script to pascal), the core of it is a decision tree looking for pixel values around a center.
That is, an offset list like that:
Code: Pascal  [Select]
  1. const fast_pixel_ring:array[0..16-1]of array[0..1]of integer=
  2. (
  3.  ( 0, 3),
  4.  ( 1, 3),
  5.  ( 2, 2),
  6.  ( 3, 1),
  7.  ( 3, 0),
  8.  ( 3,-1),
  9.  ( 2,-2),
  10.  ( 1,-3),
  11.  ( 0,-3),
  12.  (-1,-3),
  13.  (-2,-2),
  14.  (-3,-1),
  15.  (-3, 0),
  16.  (-3, 1),
  17.  (-2, 2),
  18.  (-1, 3)
  19. );
  20.  

The routine takes a pointer to a pixel in the image as input, and works through neighbor pixel values at these offsets, in form of p[offsets[n]], where p is the pointer to the center pixel, offsets is an array of offsets (multiplied by image width when applicable) that can be both positive and negative.

As you might have noticed, i ran into a problem with this on x86-64 linux - the negative offsets would cause a segmentation fault, since the compiler does not generate correct code to handle the negative case.

So, the question is - given a pointer to the middle of an array of an unknown size and start/end, how can you access an element of that array around that pointer?
In the bug report it was suggested that there is a native pointer-as-array type in pascal, but i haven't been able to find it yet.

And yes, in this example it's possible to work around the issue by shifting everything to the upper-left corner so that the offsets were always positive, but i'm after a general solution, not a special case work-around.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 4169
    • wiki
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #1 on: March 19, 2017, 09:31:35 pm »
Quote
The closest non-ugly thing i am aware of is defining an infinite array, declaring a pointer to it, and using that pointer instead of a simple pointer.

Actually that is quite ugly.

All you need is a typed pointer
Code: Pascal  [Select]
  1. type PByte  = ^Byte;
  2. var a: PByte;
  3.  
  4. a[0] := x;
  5. a[-1] := x;
  6.  
also works for ^Integer (or any type), and takes the size of integer into account.

Artlav

  • New member
  • *
  • Posts: 17
    • Orbital Designs
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #2 on: March 19, 2017, 09:40:18 pm »
All you need is a typed pointer
Which gives "Error: Array type required" in Delphi and in FPC with -Mdelphi option.
Works in FPC without the option, but that mode is completely unusable due to the lack of "result" function return variable.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5173
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #3 on: March 19, 2017, 09:56:33 pm »
In delphi (and - mode) you need to add

{$pointermath on}

so

Code: Pascal  [Select]
  1. {$ifdef fpc}
  2.  {$mode delphi}
  3. {$endif}
  4. {$pointermath on}
  5.  


or use ^
« Last Edit: March 19, 2017, 10:00:35 pm by marcov »

Artlav

  • New member
  • *
  • Posts: 17
    • Orbital Designs
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #4 on: March 19, 2017, 10:21:47 pm »
{$pointermath on}
Tried {$pointermath on}, does not help (still crashes on a negative index).

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5173
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #5 on: March 19, 2017, 10:37:33 pm »
{$pointermath on}
Tried {$pointermath on}, does not help (still crashes on a negative index).

With Martin's code? That directive removes the need for ^ and separate pointer to array declarations, also in Delphi, I use it every day.

Artlav

  • New member
  • *
  • Posts: 17
    • Orbital Designs
Re: Negative array index via variable, or how to use a pointer as array?
« Reply #6 on: March 19, 2017, 11:31:36 pm »
With Martin's code? That directive removes the need for ^ and separate pointer to array declarations, also in Delphi, I use it every day.
Ah, ok.
It works in the ^byte case and both modes.
However, it still does not work in Delphi (invalid compiler directive).

That's better than nothing - the problem can now at least be ifdef-ed away, but it's still somewhat convoluted...

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus