why use -> (not .) with pointers?

K

Keith Thompson

Ben Bacarisse said:
<snip> [...]
And suppose C201X introduced "." as a synonym for "->".
That wouldn't change the millions or billions of lines of code that
currently use "->" (and no, removing "->" from the language would not
be an option). New code using "." on pointers would not compile on
old compilers, and would inevitably be mixed with code that continues
to use "->". It would be tremendously costly with no real benefit.

I don't see the cost, at least not any tremendous cost. Do you mean
there would be a large cost from the loss of clarity in new code?

<snip>

Yes, mostly that. I suppose "tremendously costly" may have been
an overstatement. But there's also the cost of new code failing
to compile on compilers that don't yet support the new feature --
as well as the inevitable flame wars.
 
N

Nobody

s.m accesses the m member of the s struct.

p->m is syntactic sugar for (*p).m - i.e. it accesses the member of the
struct to which p points.

I'd say the opposite, namely that p.m is syntactic sugar for (&p)->m.
 
K

Keith Thompson

Nobody said:
I'd say the opposite, namely that p.m is syntactic sugar for (&p)->m.

Not quite. In the following, neither occurrence of p.m can be
legally replaced by (&p)->m:

#include <stdio.h>

struct foo {
int member;
};

struct foo func(void) {
struct foo result = { 42 };
return result;
}

int main(void) {
register struct foo reg = { 43 };
printf("func().member = %d\n", func().member);
printf("reg.member = %d\n", reg.member);
return 0;
}

Textbooks and tutorials commonly describe p->m as a shorthand for
(*p).m, which is certainly a valid description, but the standard
(C99 6.5.2.3) doesn't describe either operator in terms of the other.
 
S

Seebs

I'm wondering whether he's confusing you with someone else. Your
articles come across to me as revealing a certain amount of inexperience
with newsgroups and with C, but they don't seem hostile.

Maybe I'm confused. There were some pretty dismissive and hostile posts
by him a few weeks back, I think, but I could be wrong.
An admirable attempt at a balanced perspective - but people here tend to
have their own ways of estimating a subscriber's level of C expertise.

Yes. I have spent the last twenty years reading things people at various
levels of expertise have written about C. As an example, Schildt is clearly
experienced but careless. His mistakes are not usually newbie errors,
they're usually mistakes you'd make if you'd spent a lot of time working
with something but not paid close enough attention.

Sandeep's errors are consistently way too fundamental for that -- although
he continues to make decisions and mistakes that are hard for me to justify.
I could believe that he's got experience in some very different language
and is merely a newbie to C, but I have found his dismissive responses
(consider his endless fights with people about free(NULL), in which he
asserted that the *language specification* had overlooked something about
how implementations would work!) too annoying to put up with.

I like trying to help people who are basically able to process incoming
data. That's sorta my baseline.

-s
 
P

Peter Nilsson

Because they do different things.

That's not entirely true. Clearly they both exist to access
members of a struct or union. That they operate on different
types is not an immediate justification for different
operators. [Consider the arithmetic operators, and see below.]
Not anymore, but there were when C was first defined

I'm curious. What were the cases?
and there's never been any compelling reason to change
things.

The idea that x.m should work no matter how many levels of
indirection x requires, does have some aesthetic appeal.
Although it does seem to go against C's preserved instinct
to make pointer syntax remarkably clumsy. ;-)
 
J

James Dow Allen

I was surprised by OP's question, and slightly saddened
by most of the responses, many of which seemed to
agree with OP that the use of '->' for the '->' op
was a historical misfortune, and that a better-designed
language would overload wherever possible.

But fortunately I read down to Alan Curry's beautiful
response:

How about this for a reason: if it acts different, it should look different.
Dereferencing is different from not-dereferencing.

You found a pair of operations that could be represented by a single symbol,
since there's no set of operands that is legal for both. Does this mean it's
a good idea? No. Representing different operations with the same symbol is
called "overloading", and C is not a very overloaded language.

The arithmetic operators are pretty heavily overloaded, and this does cause
problems. Integer division gets used accidentally where floating point
division was intended. Pointer addition gets done with the wrong value
because people forget that it's automatically scaled up by the sizeof the
target.

'.' and '->' are the opposite of overloaded. They're underloaded. At any
particular spot in a program, at most one of them is legal. The distinction
between them is a pure redundancy. And redundancy is good. Redundancy allows
us to assign a meaning to only some inputs, and reject the others.

The elimination of redundancy makes more inputs meaningful, which makes the
language more delicate. It's helpful to have a lot of meaningless inputs that
near the meaningful ones, because meaningless inputs are errors detected at
compile time.

Hooray for redundancy! Hooray for meaninglessness! Hooray for underloading!

I absolutely agree with Mr. Curry. If others insist that a
"friendlier"
language would overload wherever possible, I'll answer that I fell in
love with C language because it *isn't* friendly in their sense.
It's WYSIWYG, and was often called the "portable assembler" for that
reason.

The rest of you may want languages that *guess* what you want.
Go down the hall, turn left, and look for a different language.
C does what it's told. And BTW where would you draw the line?
int a, **pp;
a += pp;
Compiler: treat 'pp' as **pp' to make it legal.
User: Oh thank you, compiler. This way I don't need
to wear out my '*' key. The '**' just confuses
my manager anyway.

x = y / 0;
Compiler: change the illegal '/' to a legal (though useless) '+'
Where do you draw the line? Maybe some day compilers will
be so much smarter than people that we expect them to silently
correct our errors. But that day is not this day.

And speaking to the question of redundancy in language, I
wish I'd saved a wonderful article in some information-theory
journal which pointed out that natural languages need to
*combine* information with redundancy. (Without the redundancy,
babies could never learn language.)

James Dow Allen
 
J

James Dow Allen

Personally, I approve wholeheartedly of the -> syntax, which I think is
a big improvement on (*). and which I would be appalled to see go.

::confused:: The debate isn't between the almost-synonyms
'(*).' and '->', but whether the compiler should silently
treat '.' as '->' when the former would otherwise be improper.
Here, in the only C program you'd ever need:
   return dwim(); /* overloaded standard library function */

I know you're being ironic, but you're lucky not to
cross-post to C++ where some would take this seriously.

I gave up pretending to try to get into the C++ spirit
when I saw an article in C/C++ User's Journal about how
to 'delete' a generic object like
struct foo {
...
struct foo *foo_friend;
}
To me this was a non-issue. The programmer deleting a
foo should know whether it's time to delete the 'friend'
as well. But the magazine article insisted on guessing
a trivial heuristic (*not using reference counts*)
so that programmers had a "worry-free" way to delete
arbitrary objects.

James
 
B

Ben Bacarisse

Peter Nilsson said:
I'm curious. What were the cases?

I posted an example elsewhere. In early C the allowable forms were:

<lvalue expression> . <member name>
<scalar expression> -> <member name>

Given

struct { char x, y; };
int i = 42;

i.x meant much the same as u.s.x does with this union:

union { int i; struct { char x, y; } s; } u = { .i = 42 };

a->x converted the scalar 'i' to a pointer type and accessed the 'x'
member. In early C, all structure members with a particular name had to
have the same type and offset so there was no question about what type
of pointer a should be converted to.

I hope someone with a longer memory will correct this if I have
miss-reported the view through the fog.

<snip>
 
S

Seebs

Given that sandeep /has/ won a technical argument, I think we could be a
little patient with him.

If the quoted responses to him show him actually accepting suggestions or
input from other people, and not doing things that look extremely and
suspiciously like intentional trolling, I'll reconsider eventually.

Thus far, he's been striking me as another Bill Cunningham. Only more
smug about how much he knows.

-s
 
N

Nick

Geoff said:
There have even been cases where I have seen p->s.m used or even
entity->client->resp.parameter.

Perfectly common. I've just dug this out of live code for your delight:

if(state->frs->plw.parent->attributes[attr_winding] || state->frs->plw.parent->attributes[attr_windable])

state is the structure pointer to the current route being planned
frs is the "for stack" - we are inside a for loop
plw is "place work" - we've made a modifiable block of place data
(and are indexing it with the integer i)
each work item contains the address of the full item for that place
each place node has a block of attributes including whether a place is
either "winding" or "windable".

If I was writing this code today, frs and plw would be longer and more
descriptive names. In fact they are the older ones, and the other stuff
with the more readable names has grown up around it.

You don't need to use . and -> and [] of course - but it does help to
work out which things are pointers and which are members.
 
M

Michael Foukarakis

Yes, just a dot is decidedly better

It might be decidedly preferable (that is completely subjective) but
it's not better. It's two operators for two different operations. If
you're so bent on '.', use (*p).m. I don't see what the big deal is.
 
A

Alexander Klauer

sandeep said:
when accessing the variables in a struct: What's the reason why in C
you have -> and . instead of only . ? Are there cases in which the
compiler couldn't figure out what to do? The problems are
1) extra typing
2) inconsistency with other languages Java, Ruby etc.
(obviously Java came later but it would be good to converge to standard
usage for accessing members)

Note that Java and a bunch of other languages (I don't know about Ruby,
though) have only one way to access members to begin with. The '.' in Java
is essentially what '->' is in C. The '.' in C has no counterpart in Java.
This is merely an extension of the fact that in C you can make a
distinction between struct and pointer-to-struct, whereas in Java you have,
besides the primitive types and the null type, only reference types.

In C, 'a->b' is syntactic sugar for '(*a).b', a token sequence already
containing a dot. At least one of the consecutive statements

*a.b;
(*a).b;

contains a syntax error. This would not be so were '.' used instead of '->'
in the grammar, creating an unnecessary source of confusion.
 
E

Ed

Michael said:
It might be decidedly preferable (that is completely subjective) but
it's not better. It's two operators for two different operations. If
you're so bent on '.', use (*p).m. I don't see what the big deal is.

I was just going to store up the answer, but you know that never works.
I'll have to come back to this when I get there. It's not timely (for me)
right now. So I'll close this with: to dot, or not to (ONLY) dot? That is
the question. :)

Feel free to continue on with this and find answer that others in the
future reading this discussion thread will find ANSWER to their question.
(I know, it is "off-topic" in c.l.c. I know! Lighten up people!).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,085
Messages
2,570,597
Members
47,220
Latest member
AugustinaJ

Latest Threads

Top