chris@mimsy.UUCP (Chris Torek) (08/10/88)
[I am moving this discussion to comp.lang.c] >In article <16734@adm.ARPA> stanonik@nprdc.arpa (Ron Stanonik) writes: >>While explaining pointers to structures someone asked why >>the -> operator was needed; ie, why couldn't the members be >>referenced as p.member. In article <474@sp7040.UUCP> jsp@sp7040.UUCP (John Peters) writes: >It needs to be referenced as a pointer. True; but to restate the question, `why does not p.member follow the pointer automagically?' >*p.member ... is the same as p->member (Someone else---ark@alice?---already corrected this, but here it is again:) No, they are not the same. In particular, * has lower precedence than ., but -> has higher precedence than .: *p.member equiv *(p.member) p->member equiv (*p).member *p->member equiv *(p->member) etc. Back to the original question, `why can't you use p.member?' The answer is `because it is defined that way'---there is (now) no particular reason for the definition, and in some other languages (Mesa) pointer.member is perfectly legal and automagically follows the pointer before selecting the member. Some people dislike this magic, although it is inherently safe (i.e., as long as the compiler is working, it will never do the wrong thing, since not following the pointer is always wrong). That is a matter of style, about which I shall follow the Roman expression and disputandem not. Was there ever a reason? Yes. Before C became strongly typed, the `. member' operation simply computed the address of the object on the left hand side of the `.', looked up the `member' name in a single global table[*], and added the offset for `member' to the address of the LHS, then grabbed the object residing in that location. Hence you could write such nonsense as float f; struct { int sign1_exp8_mant7; /* ... bits each */ }; f = 123.45; printf("exponent = %d\n", (f.sign1_exp8_mant7 >> 7) & 0377); Similarly, if you had a pointer and wanted the low byte, you could write /* remember, pdp-11 is little-endian */ struct foo { char lowbyte; char highbyte; } *p; lb = p.lowbyte; and the compiler would cheerfully extract the low byte of the pointer itself. If you wanted the low byte of the object to which p pointed, you had to write (*p).lowbyte or p->lowbyte. ----- [*] Back then all structures shared the member namespaces. This is, at least in part, the root of the format `struct garbleblotzer { int gb_thisfield, gb_thatfield; }' where an abbreviated version of the name (`gb') appears in front of every member. This served to distinguish between members of different structures that would otherwise have had the same name. With the long-since introduction of separate name spaces for each structure, this is no longer necessary, but I happen to like this format anyway, since the member name helps the reader remember the structure name. ----- Incidentally, the floating point `nonsense' above survives to this day in the 4.3BSD VAX version of `adb'. In 4.3BSD-tahoe it has been `legitimised' as (*(struct bad_programming *)&f).selector which still shows its history. I recently replaced the whole mess with a union (`in which', he says, watching the wheel whirl, `each member is at offset zero . . .'). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
karl@haddock.ISC.COM (Karl Heuer) (08/11/88)
In article <12937@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >to restate the question, `why does not p.member follow the pointer >automagically?' [Historical reason deleted] People have enough trouble with the difference between pointers and arrays. If `.' and `->' were the same operator, they'd have a similar difficulty understanding the difference between structs and struct pointers. Also, even those of us who understand the difference are likely to make a typo now and then. I prefer my typos to elicit an error message from the compiler, rather than silently guessing what I meant. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
neitzel@infbs (Martin Neitzel) (08/13/88)
btw, the debugger "dbx" will dereference a structure pointer p automatically in an expression like "p.a" And just another remark regarding the operator "->": I for one would enjoy a corresponding assignment augmentation for it: "node ->= next". (But then, I like things like APL, you know...) Martin Martin Neitzel, Techn. Univ. Braunschweig, W.Germany BITNET/EARN: neitzel@dbsinf6.bitnet (mail via bitnet preferred) UUCP: neitzel@infbs.uucp (unido!infbs!neitzel) from ARPA: neitzel%dbsinf6.bitnet@psuvax1.psu.edu
karl@haddock.ISC.COM (Karl Heuer) (08/16/88)
In article <968@infbs.UUCP> neitzel@infbs (Martin Neitzel) writes: >I for one would enjoy a corresponding assignment ... "node ->= next". It could be done, but it doesn't really fit well into the language. "->" isn't an binary operator in the usual sense, since its right operand isn't an expression. Similarly, you can't write "x -=" to mean "x = -x". Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint (Yes, the above can be written "x *= -1", but that's not the point.)