Interesting, I've seen it suggested that C doesn't need the -> operator
because . could be given this behaviour if its left operand has pointer
to struture or union type.
In my opinion the rvalues and lvalues and sequence points of C are the
abomination, and indeed Algol68 was very careful and theoretical sound
to explain what happens if you say
a := a + b ;
In C you have
a = a + b
and it is theoretical messy and very adhoc that one a is an lvalue and
one a is an rvalue.
In algol68 it says: a is the name of a place where you can store a
number. You can't add two places where you can store numbers. So we
fetch the numbers for you.
This is called coercion.
C isn't all that different. Based on the standard, in the expression
a = a + b both of the a's are lvalues. As an operand of + the 2nd a is
converted to the value of the object it designates.
Actually c does some kind of coercions : {
float b=1.;
float c;
c = 1 + b;
c = 1;
}
You can't add an int and a float. So another ad hoc rule is introduced:
both are converted to a double first. (I know, it has since been changed
into an other ad hoc rule.). In the second assignment to c, we have
again a similar situation. Suddenly it is called an "implicit cast".
These are all called conversions. There is no such thing as an "implicit
cast" in C, a cast is an operator of the form (type)expr and there is
nothing implicit about it. I have heard the term "implicit cast" used
informally but it is not terminology used in the language definition, the
correct term is "conversion".
Algol 68 said, as a general rule that an integer can be coerced into a
float and explains when and why this can be done. At least for me the
theoretical frame work was sound, and I found it much easier to remember
what an actual language construct does, than in c.
C has what it calls the "Usual Arithmetic conversions". Admittedly these
have grown a bit unwieldly as the language developed, but at least the
rules that involve floating point types aren't too bad. Rules relating to
just integers are a mess though.
....
C has never recovered from the way you have to define types (inside
out), which makes expressions like const * * const char * const p; 1)
very unintuitive.
Also invalid. Maybe a declaration like
const char **const *const p;
The things closest to p are the things that most directly define it - here
p is a const pointer to something. The something is a const pointer to
pointer to const char. You could even write it as for example
const char **const (*const p);
The vast majority of declarations are simpler than that. Perhaps the most
awkward part is that the declarator syntax includes both prefix and
postfix elements (arrays and function declarators). Perhaps if *
(indirection) was a postfix operator and declarations had a corresponding
postfix syntax for it, things would be simpler. You wouldn't need the ->
operator as ptr->member would be naturally ptr*.member. However declaring
a function that returns a pointer to char would be like
char func(arg) *;
which puts the * well away from things it relates to, especially if
there is a large parameter list.
What is worse, it survives in successors like Java and C++.
In Java the form is quite limited due to the lack of explicit pointers,
perhaps making it more manageable.
I can't find a language mistake of this magnitude in Algol68.
You may be right, but it has its charm, perhaps even some advantages.
I don't remember seeing a proposal of how a more conventional declaration
syntax might be integrated into C. I've yet to be convinced that C's way
is such a huge mistake. It seems to work well enough in practice.
Lawrence