Recent

Author Topic: Is there a function/operator in FPC that returns the offset of a field ?  (Read 5876 times)

440bx

  • Hero Member
  • *****
  • Posts: 3944
Hello,

given something like:
Code: Pascal  [Select][+][-]
  1. type
  2.   TSomeRecord = record
  3.     FirstField       : word;
  4.     SecondField      : byte;
  5.     ThirdField       : qword;
  6.   end;
  7.  

is there an "offset" function/operator that would directly return the offset of any one field in the above record ?  for instance, offset(TSomeRecord.ThirdField) would return 8 (because of alignment.)

It is easy to calculate the offset as the difference of two pointers but, it would sure be nice if there is a direct way of getting it.  That's my question, is there such a nice way of getting a field's offset ?

Thank you for your help.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #1 on: November 12, 2018, 07:20:50 am »
Afaik only like this, as you already observed:
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode delphi}{$H-}{$endif}
  2.  
  3. type
  4.   TSomeRecord1 = packed record
  5.     FirstField       : word;
  6.     SecondField      : byte;
  7.     ThirdField       : qword;
  8.   end;
  9.  
  10.   TSomeRecord2 = record
  11.     FirstField       : word;
  12.     SecondField      : byte;
  13.     ThirdField       : qword;
  14.   end;
  15.  
  16. var R1: TSomeRecord1;
  17.     R2: TSomeRecord2;
  18. begin
  19.  writeln(Addr(R1.ThirdField) - Addr(R1)); //3  
  20.  writeln(Addr(R2.ThirdField) - Addr(R2)); //8 , depending on alignment settings)
  21. end.
[/code]
« Last Edit: November 12, 2018, 07:26:14 am by Thaddy »
Specialize a type, not a var.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #2 on: November 12, 2018, 07:25:44 am »
Afaik only like this, as you already observed:
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode delphi}{$H-}{$endif}
  2. type
  3.   TSomeRecord = record
  4.     FirstField       : word;
  5.     SecondField      : byte;
  6.     ThirdField       : qword;
  7.   end;
  8.  
  9. var R: TSomeRecord;
  10. begin
  11.  writeln(Addr(R.ThirdField) - Addr(R));  
  12. end.
Thanks Thaddy.  I was afraid that would be the answer but, I figured I'd ask just in case. 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #3 on: November 12, 2018, 07:27:25 am »
I expect the compiler to use an intrinsic, but it is not public.
In assembler it is no problem.
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #4 on: November 12, 2018, 05:12:43 pm »
The following expression might look strange, but we consider it one of the official ways to retrieve the offset to a field ;)

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeRecord(Nil^).ThirdField)

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #5 on: November 12, 2018, 05:40:16 pm »
The following expression might look strange, but we consider it one of the official ways to retrieve the offset to a field ;)

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeRecord(Nil^).ThirdField)

Thank you.  I see what it does.

Definitely an improvement over using pointer difference.

It still cannot be used to define a constant equal to the offset of a field in some record.  If it could be used for that, then it would probably be a full replacement for an offset function.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #6 on: November 12, 2018, 06:13:24 pm »
That would require an extension of the macro support (the const), since it is align dependent.
Rather nifty reply from Sven... ::)
On second thought: test that!
This works:
Code: Pascal  [Select][+][-]
  1. program untitled;
  2. {$mode objfpc}
  3. type
  4.  TSomerecord = record
  5.  a:integer;
  6.  b:byte;
  7.  c:word;
  8.  end;
  9.  
  10. const
  11.   OffsetC:PtrUint = NativeUint(@TSomeRecord(Nil^).C);
  12. begin
  13.   writeln(OffsetC);
  14. end.
<grin>
« Last Edit: November 12, 2018, 06:28:52 pm by Thaddy »
Specialize a type, not a var.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #7 on: November 12, 2018, 06:44:56 pm »
@Thaddy,

The compiler is not happy with your example.  I get an "illegal expression" on the definition of OffsetC.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #8 on: November 12, 2018, 07:09:02 pm »
@Thaddy,

The compiler is not happy with your example.  I get an "illegal expression" on the definition of OffsetC.
Why does it work for me?
Specialize a type, not a var.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #9 on: November 12, 2018, 08:20:33 pm »
Why does it work for me?

I'm using FPC 3.0.4.  What FPC version are you using ?
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #10 on: November 13, 2018, 08:49:50 am »
3.2.0 and trunk 3.3.1 (daily rolling compile).
Specialize a type, not a var.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #11 on: November 13, 2018, 04:57:10 pm »
3.2.0 and trunk 3.3.1 (daily rolling compile).
That's likely why it works for you and not for me. 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

guest58172

  • Guest
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #12 on: November 13, 2018, 06:08:22 pm »
suggestions: add a `.OffsetOf` property to aggregate members. Too bad if the member is itself an aggregate type with a member called OffsetOf...
but still doable with a deprecation. 'deprecation: OffsetOf is a reserved identifier inside aggregates'.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #13 on: November 13, 2018, 11:29:33 pm »
This works for me using 1.8.4/3.0.4

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   caption := PtrUint(@TRect(nil^).top).ToSTring;
  4. end;                                              
  5.  

if you are looking for a built in function to give you an offset I am not sure how much value it would have since we can do it
this way?
« Last Edit: November 13, 2018, 11:43:06 pm by jamie »
The only true wisdom is knowing you know nothing

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #14 on: November 13, 2018, 11:36:16 pm »
This works for me using 1.8.4/3.0.4

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   caption := PtrUint(@TRect(nil^).top).ToSTring;
  4. end;                                              
  5.  
Yes, that works because caption is being assigned at run time instead of compile time.  if you try this:
Code: Pascal  [Select][+][-]
  1. const
  2.   caption : ptruint = PtrUint(@TRect(nil^).top).ToSTring;
  3.  
it won't work in FPC 3.04  (unfortunately)

But, thank you, I appreciate the help.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018