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