struct accessing

Tim McDaniel mcdaniel at uicsrd.csrd.uiuc.edu
Wed Jun 28 09:15:46 AEST 1989


In article <470001 at gore.com> jacob at gore.com (Jacob Gore) writes:
> #define TOM	(&fred_proto.tom   - &fred_proto)
> #define DICK	(&fred_proto.dick  - &fred_proto)
> #define HARRY	(&fred_proto.harry - &fred_proto)

Close, but no cigar.  The pointer subtraction yields an error message,
since &fred_proto is of type "struct fred *" and &fred.proto.tom is of
type "int *".

Suppose, instead, that it was
    #define TOM 	(&fred_proto.tom   - &fred_proto.tom)
    #define DICK	(&fred_proto.dick  - &fred_proto.tom)
    #define HARRY	(&fred_proto.harry - &fred_proto.tom)

Even if tom is the first int member of a struct fred, and all the int
members are contiguous, it still isn't guaranteed to work.  Pointer
subtraction is defined by pANS C only over pointers into the same
array.  In particular, a compiler can put an arbitrary number of bytes
of padding between struct members, and such padding wouldn't have to
be a multiple of sizeof(int) bytes long.  Such an implementation
would, in most situations, be silly, but it could happen.

Another possible solution is:

        struct fred { int tom, dick, harry; } fred_proto;

        #define TOM     offsetof(fred_proto, tom)
        #define DICK    offsetof(fred_proto, dick)
        #define HARRY   offsetof(fred_proto, harry)
        #define REF(p,f) (int *) ((char *) &p + f)

        struct fred foo;
        ...
        REF(foo,TOM) = 10;      /* sets foo.tom */

Actually, K&R's 2nd edition doesn't say anything about the "offsetof"
macro, so I had to guess about its syntax.  Also, some #include file
is needed to #define it.  Anyway, I think this is portable under pANS
C, because offsetof is required to give a field offset in bytes.  If
this use is not portable, what's the portable use of offestof?

Another requirement is implied by the original article
<1545 at stl.stc.co.uk>, in which dsr at stl.stc.co.uk (David Riches)
writes:
> Now, I have a variable which tells me the name of the field in fred
> which I would like to look at, e.g. field_name.  So if field_name
> holds the name dick I want to look at fred.dick and so on. 

The argument to REF has to be an int, not a "name".  There would have
to be some lookup table to associate a character string name with an
offset.
--
"Let me control a planet's oxygen supply, and I don't care who makes
the laws." - GREAT CTHUHLU'S STARRY WISDOM BAND (via Roger Leroux)
 __
   \         Tim, the Bizarre and Oddly-Dressed Enchanter
    \               mcdaniel at uicsrd.csrd.uiuc.edu
    /\       mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet}
  _/  \_     {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel



More information about the Comp.lang.c mailing list