www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/01/25/19:55:42

From: "John S. Fine" <johnfine AT erols DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Strange pointer manipulation
Date: Mon, 25 Jan 1999 19:51:54 -0500
Lines: 57
Message-ID: <36AD11AA.3876@erols.com>
Mime-Version: 1.0
X-Trace: k/IOXy4Lz4JPGV5SSjT5AXIL/7BjW40wSMPLeTeCzes=
X-Complaints-To: abuse AT rcn DOT com
NNTP-Posting-Date: 26 Jan 1999 00:53:07 GMT
X-Mailer: Mozilla 3.01 (Win95; U)
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

I want a decent way to make a macro, which I call undot,
that does something like the reverse of the "." operator.

  Assume you have a typdef of a struct, such as:

typedef struct {int a,b,c;} FOO;

  Now assume you have a pointer to an element of an
instance of the structure, such as:

FOO *xxx;
int *b_ptr;
b_ptr = & (xxx->b);

  Assume I know which element it points to and I know which
kind of structure it is, but I don't know which instance
of the structure it is.  I want undot to compute that, so
that  undot( b_ptr, FOO, b )  would compute the address
that started out in xxx.

  This is useful in several situations in which structures
are members of multiple trees and the general tree code
does not want to worry about which element of the structure
is being used for the current tree operation.

  The heart of the problem is representing the offset of b
within FOO in some reasonable GCC syntax.  Clearly the
compiler knows the value, since it uses it every time you
do something like (xxx->b).  But, I don't know any good
way to represent it.

  I don't need portable C;  A GCC specific kludge would be
fine.  Using a GCC specific kludge, I came close:

#define undot( ptr, typ, fld )  ( (typ *) (    \
{ typ trash;  (void *)(ptr) - (                \
(void *)&trash.fld - (void *)&trash ); } ) )

  Aside from possible conflicts on the name "trash", I think
this generates the right answer.  Unfortunately, the
optimizer can't find its way through it, so it generates
rotten code.

  I tried the following simple example:

int test(int *b_ptr) { return( undot(b_ptr, FOO, b) -> c ); }

All that is really required is to add 4 to the pointer and
indirect through it.  The kludge makes it allocate "trash"
for real, and worse yet, stops it from seeing that
((ptr-4)+8) is really (ptr+4).

  Is there some C or GCC feature that I am overlooking that
provides an easier way?
-- 
http://www.erols.com/johnfine/
http://www.geocities.com/SiliconValley/Peaks/8600/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019