[comp.lang.c] Pointers and Offsets and Shared Memory Concerns

mark@DRD.Com (Mark Lawrence) (09/26/89)

I'm implementing a shared data area which has a companion data
dictionary (also in shared memory) to describe the contents of the
shared data area.

The shared data area is implemented as one big struct with lots of
elements.  The data dictionary is defined as an array of structs, each
describing one of the elements in the shared data area.  I use #define'd
symbols as indices into the array of structs to find the description of
an element in the shared data area.  A part of the description is the
address of the element of interest.

The dictionary and the shared data area will reside in shared memory
(System V style).  I maintain a global pointer to the beginning of the
shared data area and the shared dictionary area.  

Since the shared data area could potentially get mapped in at different 
virtual memory places among user processes, I had intended to store a
relative offset from the beginning of the shared data area for an element
into the dictionary structure for that element and simply add on the base
address for the shared data area (from the user processes perspective)
at time of access to yield the 'real' virtual memory address of the
element of interest (gad, that was long).  Of course, the converse is
required at startup time to cook up the offsets in the first place, e.g.
 shdata * sdp;
 offset = &(sdp->ElementOfInterest) - sdp;
/* then stuff the offset into the relevant element of the data dictionary */

Using gcc 1.35 on SunOS 4.0.3, I find that such attempts to + and - 
pointers and addresses yields compiler complaints about invalid operands 
to binary operators.  I get this whether I cast the pointers to void * or 
char * or simply leave them typed as is.

I understand why it probably doesn't make sense (in portable way) to
simple 'add' and 'substact' pointers to come up with offsets and
recalculate, but I'm sure there is an approved way.  Can anybody give me
pointers to an operator or 'standard' macro that achieve's what I
desire?
-- 
   mark@DRD.Com                (918) 743-3013              Jer. 9:23,24
   {uunet,rutgers}!drd!mark

barmar@kulla (Barry Margolin) (09/27/89)

Since you're using GCC, and GCC claims to be pANS-conforming, it
should have the "offsetof" operator.  Given a structure and an element
of the structure, this will return the offset of the element into the
structure.

I'm surprised, however, that GCC complains when you try

 offset = (char *)&(sdp->ElementOfInterest) - (char *)sdp;

The operands to the - operator are both char*, and they both point
into the same object, so it should be OK to subtract them.  The pANS
defines the meaning of subtraction of pointers within the same object,
so the above should be portable.

Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

hunt@hobbit.DG.COM (Greg Hunt) (09/29/89)

Try this (it works for me under GCC):

#define MEMBER_OFFSET(mo_struct, mo_member) \
    ((int32_type) (char_type *) & (((mo_struct *) 0) -> mo_member))

The following operation is allowed with MEMBER_OFFSET:

    typedef any_struct_type {
        .....
        <type>          member_name_within_struct;
        .....
    } ANY_STRUCT_TYPE;

    <int32_type> = MEMBER_OFFSET (ANY_STRUCT_TYPE,
                                  member_name_within_struct);

Note that the "structure type" passed MUST be a typedef structure
name, not a typedef tag name, nor an instance of the structure.  The
member name must be within the structure, and can be any type except
bit field.

I define int32_type as long int and char_type as char.  

Hope it works for you.  

------------------------------------------------------------------
Greg Hunt                   Internet: hunt@dg-rtp.dg.com
Data General Corporation    UUCP:     {world}!mcnc!rti!dg-rtp!hunt
RTP Software Development
RTP, NC. 27713