Recent

Author Topic: indexind pointer  (Read 5332 times)

Laur

  • New Member
  • *
  • Posts: 35
indexind pointer
« on: June 24, 2024, 06:01:31 pm »
Is it allowed indexing pointers in fpas like as in c?

p : PInteger;
p[7] := 9;

simpy

instead of using pointers to array:

Type IntArray: array[1..1] of Integer;
 PIntArray = ^IntArray;

p : PIntArray;

p^[7] = 9;

I ask because I want to avoid so stupid complications.

Thanks.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8015
Re: indexind pointer
« Reply #1 on: June 24, 2024, 06:03:48 pm »
Pointer arithmetic is strongly discouraged.

If posting example code, please use appropriate tags (there's a button for it above the editing box).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11935
  • FPC developer.
Re: indexind pointer
« Reply #2 on: June 24, 2024, 06:05:55 pm »
Yes. And not only in FPC, but post 2009 Delphi also supports it, but requires a directive.

Laur

  • New Member
  • *
  • Posts: 35
Re: indexind pointer
« Reply #3 on: June 24, 2024, 06:13:33 pm »
I prefer simple arithmetic, than tremendous useless type manipulations.

Hence I propose include my option in new version of compiler.
 

MarkMLl

  • Hero Member
  • *****
  • Posts: 8015
Re: indexind pointer
« Reply #4 on: June 24, 2024, 06:21:04 pm »
I prefer simple arithmetic, than tremendous useless type manipulations.

Hence I propose include my option in new version of compiler.

In that case use some other language.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

cdbc

  • Hero Member
  • *****
  • Posts: 1649
    • http://www.cdbc.dk
Re: indexind pointer
« Reply #5 on: June 24, 2024, 06:22:51 pm »
Hi
This code below is found in 'wordcompletion.pp' under 'ide->codetools':
Code: Pascal  [Select][+][-]
  1.  
  2. procedure TWordCompletion.GetWordList(aWordList: TStrings;
  3.                                       const Filter: String;
  4.                                       ContainsFilter, CaseSensitive: boolean;
  5.                                       MaxResults: ptrint);
  6. var i, Line, x, FilterLen, MaxHash, LineLen: ptrint;
  7.   UpFilter, LineText, UpLineText, UpWordBuffer: string;
  8.   SourceText: TStrings;
  9.   HashList: ^ptrint;// index list. Every entry points to a word in the aWordList
  10.   SourceTextIndex, SourceTopLine, SourceBottomLine: ptrint;
  11.   LastCharType: TCharType;
  12.   IgnoreWordPos: TPoint;
  13.  
  14.   procedure Add(const aWord:string);
  15.   // if aWord is not already in list then add it to aWordList
  16.   var a,Hash,HashTry: ptrint;
  17.     aLowWord: string;
  18.   begin
  19.     aLowWord:=lowercase(aWord);
  20.     Hash:=0;
  21.     a:=1;
  22.     while (a <= length(aLowWord)) and (a < 20) do begin
  23.       inc(Hash,ord(aLowWord[a]) and $7f);
  24.       inc(a);
  25.     end;
  26.     Hash:= (Hash*137) mod MaxHash;
  27.     HashTry:= 0;
  28.     while (HashTry<MaxHash) do begin
  29.       a:= HashList[(Hash+HashTry) mod MaxHash];
  30.       if a >= 0 then begin
  31.         if (aWordList[a] = aWord) then
  32.           // word already in list -> do not add
  33.           exit;
  34.       end else begin
  35.         // word not in list -> add
  36.         HashList[(Hash+HashTry) mod MaxHash]:= aWordList.Add(aWord);
  37.         exit;
  38.       end;
  39.       inc(HashTry);
  40.     end;
  41.   end;
  42.  
  43.   procedure AddIfMatch(const ALine, ALineUp:string; const AFirstPos, ALength: ptrint);
  44.   var
  45.     AAdd: Boolean;
  46.   begin
  47.     if FilterLen = 0 then
  48.       AAdd:= True
  49.     else
  50.     begin
  51.       AAdd:= False;
  52.       if CaseSensitive then begin
  53.         if ContainsFilter then
  54.           AAdd:= MyPos(Filter, ALine, AFirstPos, AFirstPos+ALength-1) > 0
  55.         else
  56.           AAdd:= strlcomp(PChar(@ALine[AFirstPos]),PChar(Filter),FilterLen) = 0;
  57.       end else
  58.       begin
  59.         if ContainsFilter then
  60.           AAdd:= MyPos(UpFilter, ALineUp, AFirstPos, AFirstPos+ALength-1) > 0
  61.         else
  62.           AAdd:= strlcomp(PChar(@ALineUp[AFirstPos]),PChar(UpFilter),FilterLen) = 0;
  63.       end;
  64.     end;
  65.     if AAdd then
  66.       Add(Copy(ALine, AFirstPos, ALength));
  67.   end;
  68.  
  69. // TWordCompletion.GetWordList
  70. begin
  71.   aWordList.Clear;
  72.   if MaxResults < 1 then MaxResults:= 1;
  73.   MaxHash:= MaxResults*3;
  74.   GetMem(HashList,MaxHash*SizeOf(ptrint));
  75.   try
  76.     for i:= 0 to MaxHash-1 do HashList[i]:= -1;
  77.     FilterLen:= length(Filter);
  78.     aWordList.Capacity:= MaxResults;
  79.     UpFilter:= uppercase(Filter);
  80.     // first add all recently used words
  81.     i:= fWordBuffer.Count-1;
  82.     UpWordBuffer:= '';
  83.     while (i >= 0) and (aWordList.Count < MaxResults) do begin
  84.       if not CaseSensitive then
  85.         UpWordBuffer:= UpperCase(fWordBuffer[i]);
  86.       AddIfMatch(fWordBuffer[i], UpWordBuffer, 1, Length(fWordBuffer[i]));
  87.       dec(i);
  88.     end;
  89.     if aWordList.Count >= MaxResults then exit;
  90.     // then search in all sources for more words that could fit
  91.     SourceTextIndex:= 0;
  92.  
  93.     SourceText:= nil;
  94.     SourceTopLine:= 0;
  95.     SourceBottomLine:= -1;
  96.     IgnoreWordPos:= Point(-1,-1);
  97.     DoGetSource(SourceText,SourceTopLine,SourceBottomLine,IgnoreWordPos,SourceTextIndex);
  98.     UpLineText:= '';
  99.     repeat
  100.       if SourceText <> nil then begin
  101.         Line:= SourceTopLine;
  102.         if SourceBottomLine < 0 then
  103.           SourceBottomLine:= SourceText.Count-1;
  104.         while (Line <= SourceBottomLine) do begin
  105.           LineText:= SourceText[line];
  106.           LineLen:= length(LineText);
  107.           if not CaseSensitive then
  108.             UpLineText:= uppercase(LineText);
  109.           x:= 1;
  110.           LastCharType:= ctNone;
  111.           while (x <= LineLen) do begin
  112.             if (LastCharType = ctNone) and (CharTable[LineText[x]] = ctWordBegin)
  113.             then begin
  114.               // word found
  115.               i:= x;
  116.               repeat
  117.                 inc(i);
  118.               until (i > LineLen) or (CharTable[LineText[i]] = ctNone);
  119.               if (i-x >= FilterLen) and not ((Line = IgnoreWordPos.Y) and (x <= IgnoreWordPos.X) and (IgnoreWordPos.X<=i)) then begin
  120.                 AddIfMatch(LineText,UpLineText,x,i-x);
  121.                 if aWordList.Count >= MaxResults then exit;
  122.               end;
  123.               x:= i;
  124.             end else
  125.               inc(x);
  126.             LastCharType:= CharTable[LineText[x-1]];
  127.           end;
  128.           inc(line);
  129.         end;
  130.       end;
  131.       inc(SourceTextIndex);
  132.       SourceText:= nil;
  133.       SourceTopLine:= 0;
  134.       SourceBottomLine:= -1;
  135.       IgnoreWordPos:= Point(-1,-1);
  136.       DoGetSource(SourceText,SourceTopLine,SourceBottomLine,IgnoreWordPos,SourceTextIndex);
  137.     until SourceText = nil;
  138.   finally
  139.     FreeMem(HashList);
  140.   end;
  141. end;
Does that answer your question?!?
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

Laur

  • New Member
  • *
  • Posts: 35
Re: indexind pointer
« Reply #6 on: June 24, 2024, 06:53:12 pm »
As I can see You propose something like this:

(p+7)^ := 9

maybe:
(p+7)[0] := 9; ???

I rather cant' accept such parody...

p[7] := 9;

is much better.




WooBean

  • Sr. Member
  • ****
  • Posts: 277
Re: indexind pointer
« Reply #7 on: June 24, 2024, 07:09:08 pm »
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$Mode objFPC}
  3. (*
  4. By default, pointer arithmetic is enabled in FPC/OBJFPC modes and disabled in DELPHI mode.
  5. The directive $POINTERMATH ON/OFF can be used to toggle pointer arithmetic support. Types
  6. declared while $POINTERMATH ON is in effect also support pointer arithmetic.
  7. This boolean directive enables or disables the use of pointer arithmetic in expressions involving
  8. pointers. When enabled, the difference of 2 pointers is a valid integer expression, and an integer
  9. value can be added to a pointer value.
  10. *)
  11. const question:string = 'I ask because I want to avoid so stupid complications.';
  12. var pC:PChar;
  13. begin
  14.   pC:=@question[1];
  15.   while pC^<>#0 do begin
  16.     write(pC^);
  17.     inc(pC); //here is "pointermath"
  18.   end;
  19.   writeln;
  20.  
  21.   pC:=@question[1];
  22.   inc(pC,14); //here is "pointermath"
  23.   while pC^<>#0 do begin
  24.     write(pC^);
  25.     inc(pC); //here is "pointermath"
  26.   end;
  27.   writeln;
  28.  
  29.   readln;
  30. end.
  31.  


 output:
 I ask because I want to avoid so stupid complications.
 I want to avoid so stupid complications.


« Last Edit: June 24, 2024, 07:24:59 pm by WooBean »
Platforms: Win7/64, Linux Mint Ulyssa/64

cdbc

  • Hero Member
  • *****
  • Posts: 1649
    • http://www.cdbc.dk
Re: indexind pointer
« Reply #8 on: June 24, 2024, 07:56:13 pm »
I prefer simple arithmetic, than tremendous useless type manipulations.

Hence I propose include my option in new version of compiler.

In that case use some other language.

MarkMLl
I have to second Mark!
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

Thaddy

  • Hero Member
  • *****
  • Posts: 16160
  • Censorship about opinions does not belong here.
Re: indexind pointer
« Reply #9 on: June 24, 2024, 08:11:28 pm »
The directive is simply
Code: Pascal  [Select][+][-]
  1. {$pointermath on}
But for any "simplification" of code?
Pointer indexing is not as safe as array indexing - that is mild - and is by many considered a gimmic against the nature of the language.
I broadly agree with the comments, but the "feature" is there.
It also has not many, if any, code generation benefits. It is simply C-ism. That means you accept that your code can implode at all times. btw, array[0..0] usually makes your code unsafe too. Glad to have range checks. I assume you have only two feet. Which one do you want to shoot?
« Last Edit: June 24, 2024, 08:25:18 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10552
  • Debugger - SynEdit - and more
    • wiki
Re: indexind pointer
« Reply #10 on: June 24, 2024, 08:14:52 pm »
Pointer arithmetic is strongly discouraged.

Where? And more important, for which usecases?

If you have the option of using an array (and that is an array with correct bounds) then that is preferable, because range checks can catch errors.
If you would (have to) use a "pointer to array [0..(maxint div sizeof(element)]" => then there ain't no range checks anyway.

And then if you have a pchar or pwidechar pointing to some text in memory, would you discourage "MyPWideChar[n]" ? Because to the very best of my knowledge that uses the same pointer math as "MyPInteger[n]"



If you read some binary file (map to memory) that has some list of headers, starting with the count, and then repeat entries (where entries are all the same, e.g. all integer, or all some record), then you can't have a static array of the correct size (because each binary of that type, that you open, can have a diff count). And a dynamic array will not be useful either.
In such a case, IMHO using indexed pointer access can result in more readable and more maintainable code, then manually increasing the pointer by the amount of bytes taken by each entry.


marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11935
  • FPC developer.
Re: indexind pointer
« Reply #11 on: June 24, 2024, 08:29:08 pm »
I prefer simple arithmetic,

It has been default in Free Pascal since around 1998, and Delphi caught on in 2009.

Thaddy

  • Hero Member
  • *****
  • Posts: 16160
  • Censorship about opinions does not belong here.
Re: indexind pointer
« Reply #12 on: June 24, 2024, 08:29:46 pm »
Pointer arithmetic is strongly discouraged.
Where? And more important, for which usecases?
The only use case to the contrary I can think of is to use it with pointers on the stack, because of limited stack size.
(that's where the array[1..1] comes from)
Just use array indexing otherwise.
If I smell bad code it usually is bad code and that includes my own code.

440bx

  • Hero Member
  • *****
  • Posts: 4731
Re: indexind pointer
« Reply #13 on: June 25, 2024, 01:07:34 am »
The only use case to the contrary I can think of is to use it with pointers on the stack, because of limited stack size.
(that's where the array[1..1] comes from)
Just use array indexing otherwise.
Far from the only use case.

A very common use case is when dynamically allocating an array of pointers to some structure.  In those cases, it is often simpler and much more convenient to calculate the end address of the array than it is to keep track of the number of elements and use array indexing.  IOW, it simpler and easier to understand to have "while TheAddress < EndAddresss do <whateverneedstobedone>;" than having to use the count of elements to limit the loop (not to mention the commonly overlooked need to subtract 1 from the count.)

And that's when the elements are of fixed size, if they are variably sized (such as CPU instructions), attempting to use only array notation won't work.  (In that case, a combination of both often provides reasonably good results.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Laur

  • New Member
  • *
  • Posts: 35
Re: indexind pointer
« Reply #14 on: June 25, 2024, 05:13:48 pm »
I dont' see any revelation in pointer indexing.

var p : PDouble;
    n : Integer;

.... some code

and:

p := GetMem(sizeof(Double)*n);

for i :=  0 to N-1 do
 p := sin(i*pi/N);

...

this is safe, and natural;
..
finally: FreeMem(p);


arrays are just pointers in fact - nothing specjal.

Pointer to record, object - the same... it's just a memory.

Aq : array[0..n] of windows; // ?

this is stupid. :)

pWins: PWindow; // is much better. :)


.............

can resize array?

of course!

procedure addE(var e : E);
begin
 if limit == count then realoc(p, inc(limit,100));
...
end;
« Last Edit: June 25, 2024, 05:20:54 pm by Laur »

 

TinyPortal © 2005-2018