From: "John S. Fine" 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 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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/