stanonik@nprdc.arpa (Ron Stanonik) (08/04/88)
While explaining pointers to structures someone asked why the -> operator was needed; ie, why couldn't the members be referenced as p.member. My first response was, we're talking about pointers to structures, not structures, so a separate operator is needed. On second thought though, since the compiler knows whether the variable is a pointer or structure, why shouldn't the compiler do the "right" thing when it sees p.member? Could this ever be ambiguous? That is, is there some declaration of p such that p could be interpreted as both a structure and a pointer to a separate structure. I tried fiddling around with unions, but could not produce such an object. Does it make a lot more work for the compiler? It doesn't seem so, since it's already keeping track of p's type. Thanks, Ron Stanonik stanonik@nprdc.arpa
karish@denali.stanford.edu (Chuck Karish) (08/04/88)
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. This is explained in p. 122 of K&R, first edition. Briefly, if we define a structure pointer with struct date { int year, month, day } *pd; then pd->year is equivalent to (*pd).year. The parentheses show that we're dereferencing pd, not year. Interpretation of the sort you discuss, in which the compiler figures out automatically that p is a pointer and decides on its own to dereference it, would be pretty confusing, not to mention inconsistent with the way other pointers are handled. Anyway, it's not part of the language. Chuck Karish ARPA: karish@denali.stanford.edu BITNET: karish%denali@forsythe.stanford.edu UUCP: {decvax,hplabs!hpda}!mindcrf!karish USPS: 1825 California St. #5 Mountain View, CA 94041
ash@a.cs.okstate.edu (Ashok Rathi) (08/06/88)
"p.member" will be interpreted as "p" being the name of the structure and "member" being the element of that structure. While "p->member" will be interpreted as "p" being the pointer to the structure and "member" being the structure itself or the element of the structure. In one case, "p" is the structure and in another a pointer to the structure. Compiler must know what is what since it has to allocate the space accordingly.
jsp@sp7040.UUCP (John Peters) (08/08/88)
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. It needs to be referenced as a pointer. To do that use: *p.member it is the same as p->member -- Johnnie --
merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) (08/09/88)
In article <474@sp7040.UUCP>, jsp@sp7040 (John Peters) writes: | 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. | | It needs to be referenced as a pointer. To do that use: | | *p.member | | it is the same as | | p->member Whup. Not quite. *p.member is *(p.member). Try (*p).member instead. That's one reason the -> syntax was introduced (from what I remember in reading the white Bible) -- to prevent having to do a lot of parens for a fairly common operation. Another example: can you imagine typing (*((ARR)+(x+y))) every time you wanted ARR[x+y]? But, the real question (as far as it has been discussed in lang.c, I guess) is "if only pointers are used in ->, and structs in ., howcum the compiler can't figure it out?" Because, it is not PL/1. I don't want an automatic conversion. If I type something like indexvalues[j]->fred[3] += 17 I want to be warned if I forgot that indexvalues is really an array of structs, not array of pointer to struct. Automatic adjustment could lead to maintenance headaches later, or even debugging headaches before it works the first time. Just an opinion. But then again, most of what get said here is. :-) -- Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 on contract to BiiN Technical Publications (for now :-), Hillsboro, Oregon <merlyn@intelob.intel.com> or ...!tektronix!ogcvax!omepd!intelob!merlyn Standard disclaimer: I *am* my employer!
ark@alice.UUCP (08/10/88)
In article <474@sp7040.UUCP>, jsp@sp7040.UUCP writes: > It needs to be referenced as a pointer. To do that use: > > *p.member > > it is the same as > > p->member I'm going to ignore the original question and merely point out that *p.member means the same as *(p.member) which, in turn, is quite different from p->member In fact, p->member means the same thing as (*p).member
maart@cs.vu.nl (Maarten Litmaath) (08/10/88)
In article <474@sp7040.UUCP> jsp@sp7040.UUCP (John Peters) writes:
\ *p.member
\
\it is the same as
\
\ p->member
(*p).member, please.
Back to Basic on your C64, Buddy.
--
If you enjoyed the recent heat wave, |Maarten Litmaath @ Free U Amsterdam:
you'll certainly like the ozone gap...|maart@cs.vu.nl, mcvax!botter!maart
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
dg@lakart.UUCP (David Goodenough) (08/11/88)
From article <474@sp7040.UUCP>, by jsp@sp7040.UUCP (John Peters): > 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. > > It needs to be referenced as a pointer. To do that use: > *p.member > it is the same as > p->member Not quite - the correct form is: (*p).member Check P. 49 of the gospel according to Kernighan and Ritchie for reasons. However this all explains what it is all about (for more info see K&R P. 122) -- dg@lakart.UUCP - David Goodenough +---+ | +-+-+ ....... !harvard!cca!lakart!dg +-+-+ | +---+
jerry@olivey.olivetti.com (Jerry Aguirre) (08/11/88)
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. Now that everyone has explained what the difference between p. and p-> is and what they each mean (which he alread knew), how about answering the question? As a precedent the compiler already handles this type of conversion for arrays. I can declare: char b1[10]; char *b2; and then later refer to both of them as: b1[2] = b2[2]; Now one of these is the actual array and the other is a pointer. The compiler has to generate the same type of derefferencing that it would for a structure refference. I have had real trouble trying to explain this difference to novice C programmers. In particular the difference between: extern char *b1; and extern char b1[]; seems to confuse anyone used to a higher level language. Many will insist that the manual says they mean the same thing. Getting back to structures though. The final point is that if the compiler can tell the difference then it is one less detail for the programmer to worry about. As long as old code would still work then there should be no problem, right? Jerry Aguirre
greim@sbsvax.UUCP (Michael Greim) (08/11/88)
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. My first response was, we're talking >about pointers to structures, not structures, so a separate >operator is needed. On second thought though, since the >compiler knows whether the variable is a pointer or structure, >why shouldn't the compiler do the "right" thing when it sees >p.member? > >Could this ever be ambiguous? That is, is there some declaration >of p such that p could be interpreted as both a structure and >a pointer to a separate structure. I tried fiddling around >with unions, but could not produce such an object. Yes, there is something which the compiler cannot decide. Suppose you have a function a (s) struct some_struct s; and you want to call it. So you say struct some_struct * s; ... a (s); What should the compiler do? Do you want the pointer by itself or do you want to pass the structure s is pointing to? In a the compiler must know what the parameters will be like. It will have problems if the declaration of a is not in the same file as the call. Or suppose you do struct some_struct * s; ... p = &s; Do you want the address of s or of the structure s is pointing at ? Or course one could devise some clever algorithm which elaborates on "if a pointer happens to come along in a function call then create and pass a record which holds a flag, so that the called function can tell looking at its parameters what it really has been called with and convert and copy the real actual parameter accordingly." (If you are running VMS you get those nifty descriptors by which a called function really sees what is passed. Or so the theory seems to go. Overhead, if you ask me. In each program I write under VMS I stumble across some case where I have to outwit this mechanism. I would not be anstonished to hear that in VMS C the actual parameters are passed as descriptors pointing at descriptors pointing at ... :-) But such a concept is - difficult to remember : what do you expect, how often will you be wondering : "is the compiler really doing what I think it is ?" (Also called the "I wanted this ADA program to count to 10 and now it is sending my filled out tax forms to 20.000 people ???"-syndrom :-) - confusing : it makes one confuse pointers with structures. And sometimes you need to understand the differences to know what the program does. - generating difficulties in the compiler - making programs more difficult to understand To conclude : it might be possible, but what would it be worth? -mg -- +------------------------------------------------------------------------------+ | UUCP: ...!uunet!unido!sbsvax!greim | Michael T. Greim | | or greim@sbsvax.UUCP | Universitaet des Saarlandes | | CSNET: greim%sbsvax.uucp@Germany.CSnet| FB 10 - Informatik (Dept. of CS) | | ARPA: greim%sbsvax.uucp@uunet.UU.NET | Bau 36, Im Stadtwald 15 | | Phone: +49 681 302 2434 | D-6600 Saarbruecken 11, West Germany | +------------------------------------------------------------------------------+ | # include <disclaimers/std.h> | +------------------------------------------------------------------------------+
barmar@think.COM (Barry Margolin) (08/12/88)
In article <3740@omepd> merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) writes:
]But, the real question (as far as it has been discussed in lang.c, I
]guess) is "if only pointers are used in ->, and structs in ., howcum
]the compiler can't figure it out?"
]Because, it is not PL/1. I don't want an automatic conversion.
Ahem! PL/I refuses to do this particular conversion, too. In fact, I
think PL/I originated the "->" syntax for pointers (did Algol-60 have
pointers?).
Barry Margolin
Thinking Machines Corp.
barmar@think.com
{uunet,harvard}!think!barmar
gwyn@smoke.ARPA (Doug Gwyn ) (08/12/88)
In article <25559@think.UUCP> barmar@kulla.think.com.UUCP (Barry Margolin) writes: >(did Algol-60 have pointers?). Yes, but they weren't typed. What does this have to do with UNIX?