Path: utzoo!attcan!utgpu!watmath!watcgl!jvkelley From: jvkelley@watcgl.waterloo.edu (Jeff Kelley) Newsgroups: comp.sys.amiga.tech Subject: Determining structure field offsets Keywords: Lattice C 5.02 Message-ID: <9270@watcgl.waterloo.edu> Date: 17 Apr 89 13:54:06 GMT Distribution: comp Organization: U of Waterloo, Ontario Lines: 62 What's the best way to determine the offset of a field of a structure? For example, if I have: struct foobar { int foo; int bar; }; how can I determine the offset of the 'bar' field in a manner independent of preceding fields? My initial attempt was to use a macro of the form: #define STRUCT_OFFSET(structure, field) \ ((int)&((structure *)0)->field) used like: offset = STRUCT_OFFSET(struct foobar, bar); However, compiling with Lattice C 5.02 produces the Error "Invalid structure reference" for this statement. If the 0 in the macro is changed to something else, though, such as a 1, no error is produced. Of course, we have to subtract 1 to compensate, so we get: #define KLUDGE 1 #define STRUCT_OFFSET(structure, field) \ ((int)&(((structure *)KLUDGE)->field)-KLUDGE) This would be satisfactory (although I still don't understand why 0 doesn't work) except that the compiler produces pretty bad code, something like: movea.w #1,a0 lea 4(a0),a1 move.l a1,d0 move.l d0,d7 * subq.l #1,d7 move.l d7,d0 * (The two '*'ed statements are effectively eliminated by the 'global optimizer'.) It seems to be a rather poor way of doing a moveq.l #4,d0 which is generated by the GNU C compiler, at least when KLUDGE is 0 (which doesn't produce an error with GNU C). Couldn't the compiler do some expression tree analysis and reduction? Seeing code like this makes me want to quit working as a programmer and take up fish-farming in Alaska :-) For an example of how this facility might be used, consider a memory allocation scheme which records the size of the memory allocated in the first longword of the allocated block, then returns a pointer to the remainder to the user. i.e. struct Block { long size; char user_area }; When the user calls 'free(block)' or whatever, in order to find the block size you need to subtract the offset of the user_area field from the pointer the user gives you. Subtracting 'sizeof(long) ' or 'sizeof(block->size)' doesn't cut it (in my opinion) because it doesn't track changes to the structure. Any and all help is appreciated. -- Jeff Kelley National Research Council of Canada, Ottawa uunet!watmath!watcgl!jvkelley tel: (613) 990-5924