>In article <878wyjqqfp.fsf@[EMAIL PROTECTED]
> Keith Thompson <kst-u@[EMAIL PROTECTED]
>
>writes:
>>There are languages that allow the prefix to the "." "operator"
>>to be either a structure or a pointer to structure. ...
In article
<e6a059bc-ec27-4f43-a1b6-0dcc65beef43@[EMAIL PROTECTED]
>
Bart <bc@[EMAIL PROTECTED]
> wrote:
>So the left side side of "." is not just a struct type, but any chain
>of pointers to a struct, multi-dereferenced as necessary to get at the
>struct that "." needs? (This shows up a weakness in -> which can only
>deal with one dereference at a time.)
In the languages that I know about that allow either structure
or pointer-to-structure before ".member", no: only one "level"
of pointer-ness is allowed. That is, in a modified C in which
"p.foo" were accepted given "struct S *p", if this modified C
were like these other languages, given "struct S **pp;", "pp.foo"
would still be an error.
(In this modified C, however, you could then use "(*pp).foo"
the way you now can use "(*pp)->foo".)
>>Footnote 4: Obviously Ritchie *didn't* decide to define "." this
>>way, either by the conversion method or by making it polymorphic.
>>I wouldn't look for any deeper meaning in this decision. Probably
>>he just thought of accessing a member of a structure directly and
>>accessing the same member via a pointer to the structure as two
>>distinct operations, calling for two distinct syntaxes (or perhaps
>>the decision was inherited from B or BCPL). It's a decision that
>>could reasonably have been made either way.
In early C, the "->" and "." "operators" (I use quotes around
operator for the same reason Keith Thompson did) never bothered to
check the types of their left-hand-side "operands". The following
were allowed, and both were in fact used:
struct {
char lo, hi;
};
int i;
...
printf("%o %o\n", i.lo, i.hi);
struct {
int csr;
int bar;
int cnt;
};
...
0777440->bar = addr;
(Do not try this with a modern C compiler. :-) ) The -> "operator"
simply *assumed* the left "operand" was a pointer and followed it,
while the "." "operator" simply *assumed* that the right "operand"
was an appropriate structure. Both then simply added the member-offset
to the "address" derived by lvaule-style evaluation of the thing
on the left, and treated the resulting address as if it were an
object whose type was given by the member-name on the right.
Because -> and . did not look at their left sides, all structure
(and union) member names *had* to be unique. That is, doing
something like:
struct list_of_X {
int x_value;
struct list_of_X *next;
};
struct list_of_Y {
double y_value;
double y_associate;
struct list_of_Y *next;
};
would fail, because the member named "next" had to have two different
offsets (2 and 10, since sizeof(int)==2 in this early version of
C). The compiler did not bother to see whether p->next or t.next
wanted an "X next" or a "Y next", so having two different kinds of
"next"s would be impossible. This is why Unix-like systems have,
for instance, all of the members of "struct stat" named "st_foo":
the st_ prefix made all the member names distinct, so that you
could use both a "struct stat" (with its st_ino) and a "struct
direct" (with its d_ino) without having the two "ino" member names
cla****ng.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html


|