Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!cs.utexas.edu!csd4.milw.wisc.edu!mailrus!ncar!tank!uxc.cso.uiuc.edu!garcon!uicsrd.csrd.uiuc.edu!mcdaniel From: mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) Newsgroups: comp.lang.c Subject: Re: struct accessing Message-ID: <1379@garcon.cso.uiuc.edu> Date: 27 Jun 89 23:15:46 GMT References: <1545@stl.stc.co.uk> <470001@gore.com> Sender: news@garcon.cso.uiuc.edu Reply-To: mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) Organization: Center for Supercomputing R&D (Cedar), U. of Ill. Lines: 59 In article <470001@gore.com> jacob@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@stl.stc.co.uk>, in which dsr@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@uicsrd.csrd.uiuc.edu /\ mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet} _/ \_ {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel