Translate C code

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Translate C code

Darius Blaszyk
Hi all,

Again I would like to ask some support on a piece C code that I need to translate to pascal. The code in question is:

#define MEMNEXT(x) ((MyStruct *)(((char *) x) - ((char *) & (((MyStruct *)0)->next))))

What exactly is going on here? Where does the result point to? It seems like it starts with the pointer x and subtracts the size of the offset of the beginning of MyStruct up to the "next" variable. At least that's what I think is happening.

Does anyone has an idea how to translate this into working pascal code?

TIA!

Rgds, Darius

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Karoly Balogh (Charlie/SGR)
Hi,

On Sat, 6 Jan 2018, Darius Blaszyk wrote:

> Again I would like to ask some support on a piece C code that I need to
> translate to pascal. The code in question is:
>
> #define MEMNEXT(x) ((MyStruct *)(((char *) x) - ((char *) & (((MyStruct *)0)->next))))
>
> What exactly is going on here? Where does the result point to? It seems
> like it starts with the pointer x and subtracts the size of the offset
> of the beginning of MyStruct up to the "next" variable. At least that's
> what I think is happening.

Yes, it looks like it. It simply substracts the offset of the "next" field
from the value of X; This is a better solution than hardwiring the offset
of next, which could change depending on the target platform's structure
padding, or other reasons (and sometimes could be hard to calculate by
hand anyway).

> Does anyone has an idea how to translate this into working pascal code?

Well, not sure why one needs to do this abomination, without knowing the
data structure it operates on, but nevertheless, you can do the same in
Free Pascal, but you better turn the macro into a function:

type
  PMyStruct = ^TMyStruct;
  TMyStruct = record
    some, fields: integer;
    next: PMyStruct;
  end;

function MEMNEXT(x: Pointer): PMyStruct;
begin
  MEMNEXT:=PMyStruct(PByte(x)-PByte(@(PMyStruct(nil)^.next)));
end;

If this function is used often, you can mark it as inline; So the compiler
can inline it, whenever necessary. If you want to avoid pointermath for
whatever reason, the same works if you cast the pointers to PtrUInt
instead of a PByte.

If the input value of X is other than a pointer, you can either overloaded
methods, or define a var parameter without type, for example.

Charlie
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Darius Blaszyk
> Well, not sure why one needs to do this abomination, without knowing
> the
> data structure it operates on, but nevertheless, you can do the same in
> Free Pascal, but you better turn the macro into a function:

Thanks Charlie!
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Ryan Joseph
In reply to this post by Karoly Balogh (Charlie/SGR)


> On Jan 6, 2018, at 1:49 PM, Karoly Balogh (Charlie/SGR) <[hidden email]> wrote:
>
> type
>  PMyStruct = ^TMyStruct;
>  TMyStruct = record
>    some, fields: integer;
>    next: PMyStruct;
>  end;
>
> function MEMNEXT(x: Pointer): PMyStruct;
> begin
>  MEMNEXT:=PMyStruct(PByte(x)-PByte(@(PMyStruct(nil)^.next)));
> end;

I’m curious about how this is intended to be used. What would the value of x be? This looks like a confusing way to write sizeof(TMyStruct) - Sizeof(pointer) but I’m confused myself.

Also why does @(PMyStruct(nil)^.next not crash? Dereferencing and taking the addressing of a nil pointer sounds like a bad idea.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Karoly Balogh (Charlie/SGR)
Hi,

On Sat, 6 Jan 2018, Ryan Joseph wrote:

> Also why does @(PMyStruct(nil)^.next not crash? Dereferencing and taking
> the addressing of a nil pointer sounds like a bad idea.

Because it doesn't do the actual dereferencing, because next's *VALUE* is
never used, only it's address (due to the @ operator). Which is basically
a fixed address of zero (nil) + a constant added together.

So it doesn't crash, because it never loads from this "invalid" address it
calculates.

Charlie
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Giuliano Colla
In reply to this post by Darius Blaszyk

Il 06/01/2018 01:39, Darius Blaszyk ha scritto:

#define MEMNEXT(x) ((MyStruct *)(((char *) x) - ((char *) & (((MyStruct *)0)->next))))

h2pas translates it into the enclosed file.
Hope that it helps.

Giuliano



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

darius.pp (756 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Ryan Joseph
In reply to this post by Karoly Balogh (Charlie/SGR)


> On Jan 6, 2018, at 5:25 PM, Karoly Balogh (Charlie/SGR) <[hidden email]> wrote:
>
> So it doesn't crash, because it never loads from this "invalid" address it
> calculates.

Are we talking about the address on the stack at compile time? If no memory was ever allocated (which I thought nil suggested) then I don’t see where it’s getting an address of anything.

For anyone interested can you recode that function to more Pascal? It feels like we’re going needlessly low level when another method would make more sense.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Translate C code

Free Pascal - General mailing list
Am 06.01.2018 12:23 schrieb "Ryan Joseph" <[hidden email]>:


> On Jan 6, 2018, at 5:25 PM, Karoly Balogh (Charlie/SGR) <[hidden email]> wrote:
>
> So it doesn't crash, because it never loads from this "invalid" address it
> calculates.

Are we talking about the address on the stack at compile time? If no memory was ever allocated (which I thought nil suggested) then I don’t see where it’s getting an address of anything.

In this case Nil does in fact have the address 0. Thus the address of a field in a record with address 0 is its offset in the record. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal