Recent

Author Topic: Can this C struct be expressed in FPC Pascal ?  (Read 19260 times)

440bx

  • Hero Member
  • *****
  • Posts: 3944
Can this C struct be expressed in FPC Pascal ?
« on: July 06, 2019, 03:01:06 am »
Hello,

In C, it is possible to define a structure as follows:
Code: C  [Select][+][-]
  1. typedef struct mystruct
  2. {
  3.   DWORD a;
  4.   DWORD b;
  5.   DWORD c[];
  6. };
  7.  
The part that is notable is the definition of the field "c" as an array of DWORDs and that this array takes no space in the structure.  It is just there to allow the programmer to reference that location (after variable b).

Is there a way in FPC to declare a field in a record that takes no space and is there only to provide a way to reference that location in the record ?

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.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #1 on: July 06, 2019, 03:10:22 am »
It's a flexible array member
https://en.wikipedia.org/wiki/Flexible_array_member

Is there a way in FPC to declare a field in a record that takes no space and is there only to provide a way to reference that location in the record ?
No. The "static" part should become the record. The flexible part should be read separately.

You can however, declare an additional structure that would cover for "flexible array member".
Code: Pascal  [Select][+][-]
  1. mystruct = packed record
  2.   a,b: DWORD;
  3. end;
  4.  
  5. mystruct_full = packed record
  6.   hdr : mystruct;
  7.   c : array[byte] of DWORD;
  8. end;
  9.  
as a result you can access "c" array using mystruct_full, BUT
you'll run into a range-check error, (if these are enabled), whenever you'd access c[] outside of declared boundaries (in this case it's "byte", but you could set it to "word")

also, sizeof(mystruct_full)   would obviously be greater than sizeof(mystruct)
While sizeof(mystruct) between C and Pascal would match in this case.
« Last Edit: July 06, 2019, 03:14:11 am by skalogryz »

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #2 on: July 06, 2019, 03:39:43 am »
No. The "static" part should become the record. The flexible part should be read separately.
Thank you.  I wanted to make sure I didn't know of some FPC feature that would allow an equivalent/parallel construction.

You can however, declare an additional structure that would cover for "flexible array member".
Code: Pascal  [Select][+][-]
  1. mystruct = packed record
  2.   a,b: DWORD;
  3. end;
  4.  
  5. mystruct_full = packed record
  6.   hdr : mystruct;
  7.   c : array[byte] of DWORD;
  8. end;
  9.  
as a result you can access "c" array using mystruct_full, BUT...
yes, that sounds right.  It works using "absolute" to overlay the full struct over the "truncated" struct.  I tried a typecast and FPC complained about it being an invalid typecast (absolute works, that's good enough.)

also, sizeof(mystruct_full)   would obviously be greater than sizeof(mystruct)
While sizeof(mystruct) between C and Pascal would match in this case.
Yes, there are some "details" that one must be careful with (such as size)

That was helpful, thank you again.

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

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #3 on: July 06, 2019, 07:25:23 am »
I find it unpleasant to have to define two records to achieve the same result of one structure in C. Not to mention the possibility of using the wrong size.

I would use:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch advancedrecords}
  5.  
  6. Type
  7.   mystruct = packed record
  8.   private
  9.     function Getc(i: integer): DWORD; inline;
  10.   public
  11.     a,b: DWORD;
  12.     property c[i: integer]: DWORD read Getc;
  13.   end;
  14.  
  15. function mystruct.Getc(i: integer): DWORD;
  16. begin
  17.   Result := PDWORD(@self.b)[1+i]; // or PDWORD(sizeOf(self)+pbyte(@self))[i] or ...etc;
  18. end;
  19.  
  20. var
  21.   a: array[0..5] of DWord = (0,1,2,3,4,5);
  22.   sample: mystruct absolute a;
  23.  
  24. begin
  25.   WriteLn('Size: ', SizeOf(mystruct));
  26.   WriteLn('a: ', sample.a);
  27.   WriteLn('b: ', sample.b);
  28.   WriteLn('c[0]: ', sample.c[0]);
  29.   WriteLn('c[1]: ', sample.c[1]);
  30.   WriteLn('c[2]: ', sample.c[2]);
  31.   WriteLn('c[3]: ', sample.c[3]);
  32.  
  33.   ReadLn;
  34. end.

As you can see, c does not occupy any memory.

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #4 on: July 06, 2019, 07:37:48 am »
I find it unpleasant to have to define two records to achieve the same result of one structure in C. Not to mention the possibility of using the wrong size.

I would use:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch advancedrecords}
  5.  
  6. Type
  7.   mystruct = packed record
  8.   private
  9.     function Getc(i: integer): DWORD; inline;
  10.   public
  11.     a,b: DWORD;
  12.     property c[i: integer]: DWORD read Getc;
  13.   end;
  14.  
  15. function mystruct.Getc(i: integer): DWORD;
  16. begin
  17.   Result := PDWORD(@self.b)[1+i]; // or PDWORD(sizeOf(self)+pbyte(@self))[i] or ...etc;
  18. end;
  19.  
  20. var
  21.   a: array[0..5] of DWord = (0,1,2,3,4,5);
  22.   sample: mystruct absolute a;
  23.  
  24. begin
  25.   WriteLn('Size: ', SizeOf(mystruct));
  26.   WriteLn('a: ', sample.a);
  27.   WriteLn('b: ', sample.b);
  28.   WriteLn('c[0]: ', sample.c[0]);
  29.   WriteLn('c[1]: ', sample.c[1]);
  30.   WriteLn('c[2]: ', sample.c[2]);
  31.   WriteLn('c[3]: ', sample.c[3]);
  32.  
  33.   ReadLn;
  34. end.

As you can see, c does not occupy any memory.
Yes, excellent idea.  The property "c" in Pascal becomes the offset marker "c" in the C struct.  That is really good. :)

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

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #5 on: July 06, 2019, 08:08:17 am »
And if you are bothered by the verbosity of the previous Pascal property, and don't mind seeing pointers (I am sure you don't):
Code: Pascal  [Select][+][-]
  1.   mystruct = packed record
  2.     a,b: DWORD;
  3.     function c: PDWORD; inline;
  4.   end;
  5.  
  6. function mystruct.c: PDWORD;
  7. begin
  8.   Result := PDWORD(pbyte(@self.b)+sizeOf(self.b));
  9. end;

of course, you can still access "c" as an open array to read/write its values:
Code: Pascal  [Select][+][-]
  1.   sample.c[i] := i+1
« Last Edit: July 06, 2019, 08:09:48 am by engkin »

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #6 on: July 06, 2019, 08:37:13 am »
And if you are bothered by the verbosity of the previous Pascal property, and don't mind seeing pointers (I am sure you don't):
Code: Pascal  [Select][+][-]
  1.   mystruct = packed record
  2.     a,b: DWORD;
  3.     function c: PDWORD; inline;
  4.   end;
  5.  
  6. function mystruct.c: PDWORD;
  7. begin
  8.   Result := PDWORD(pbyte(@self.b)+sizeOf(self.b));
  9. end;

of course, you can still access "c" as an open array to read/write its values:
Code: Pascal  [Select][+][-]
  1.   sample.c[i] := i+1
I like this one even better :)

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

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #7 on: July 06, 2019, 09:38:02 am »
This is what we call a "buffer overrun".

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #8 on: July 06, 2019, 09:45:41 am »
Intentional.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #9 on: July 06, 2019, 10:29:41 am »
This is what we call a "buffer overrun".
Not if the memory backing the record is intentionally large enough (of course you shouldn't use it as a stack variable, but only as a pointer). Such constructs are often encountered when dealing with C code (see the other thread where this was talked about).

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #10 on: July 06, 2019, 05:02:16 pm »
With range check off... and I hope they never disable this feature because its going to cause a lot of translation
issues if they do....

Code: Pascal  [Select][+][-]
  1. TmyRecord = Packed Record
  2.     A:Dword;
  3.     Case Integer of
  4.       0:(B:Dword;);
  5.       1:(C:Array[-1..-1] of DWord);
  6.  end;                                      
  7.  

{$R-}
 MYRecordInstance.C[0..?]…..


 Doing this the size of the record it exactly 8 bytes to account for the A,B Dword and using a case like this..

It would be nice if Fpc had a C:Array[] of Dword; so that it can generate a location without an instance.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #11 on: July 06, 2019, 05:12:03 pm »
Example of use

Code: Pascal  [Select][+][-]
  1. {$Push}
  2. {$R-}
  3.  M := GetMem(1000);
  4.  TMyRecord(m^).C[10] := 1;
  5.  FreeMem(M);
  6.  {$pop}                      
  7.  
The only true wisdom is knowing you know nothing

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #12 on: July 06, 2019, 05:20:38 pm »
An empty record is sometimes used to create such identifier at the end of the record, but it of course doesn't have the typing like in C. Pascal is not big on out of bounds accesses by design.

Code: Pascal  [Select][+][-]
  1. type
  2.   TDummy = record end;
  3.   mystruct =record
  4.               a,b :DWord;
  5.                c:Tdummy;
  6. end;
  7.  
  8. begin
  9.   writeln(sizeof(mystruct)); // prints 8.
  10. end.
  11.  

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #13 on: July 06, 2019, 05:30:46 pm »
If you really want to program in Pascal like in C, use pointers. Don't rape the language.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Can this C struct be expressed in FPC Pascal ?
« Reply #14 on: July 06, 2019, 05:36:14 pm »
The example I present I've used many times in Delphi and generally It works  but it isn't perfect because
the previous type isn't always optimum to give you the same type size so you need to fool with the index
range to fix that..

 I think this feature of empty array definitions should be implemented because it would allow rangeless
accessing of the array and not create a body instance.

 C:Array[] of Dword; in a Record would be perfect but it would need to be the last and final type in the
record.
 Also one could just bundle a list of different types at the end which would all fall on the same address bounds
 C:Array[] of Dword;
 D:Array[] of Word;

etc.


The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018