why use -> (not .) with pointers?

F

Felix Kater

Hi,

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?

Felix
 
S

Suman

Felix said:
Hi,

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?
-> is used when you have a pointer to a struct, and you are trying to
access
elements of the struct whose address is stored in the pointer.

.. is used when you have an object of a struct, and you are trying to
access
elements of the struct.

Does that help?
 
J

jacob navia

Felix said:
Hi,

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?

Felix
I think the answer is NO, there aren't any reasons why
the distinction exists since the compiler can always
figure it out.

If we would always use '.' and there was a pointer, the
compiler could test if we have instead of a structure,
a pointer to a structure, then generate a dereferencing of
the pointer without much trouble.

The best way to do this is to deprecate '->'

But, helas, this is not going to happen any time soon.

jacob
 
J

jacob navia

Suman said:
-> is used when you have a pointer to a struct, and you are trying to
access
elements of the struct whose address is stored in the pointer.

. is used when you have an object of a struct, and you are trying to
access
elements of the struct.

Does that help?

You didn't answer the question!

My answer is no. See elsewhere in this thread
 
R

Richard Tobin

Suman said:
-> is used when you have a pointer to a struct, and you are trying to
access elements of the struct whose address is stored in the pointer.

. is used when you have an object of a struct, and you are trying to
access elements of the struct.

I think the original poster knows that. Since there is no context
where both a.b and a->b are legal, he is asking why C doesn't use the
same syntax for both.

I think the answer is just that they are different operations so C has
different names for them. a->b is equivalent to (*a).b. A less
explicit language than C might confound these, but C doesn't.

-- Richard
 
C

Chris Dollin

Felix said:
when accessing the variables in a struct: What's the reason why in C
you have -> and . instead of only . ?

Historical. I seem to recall . came first, -> came later.
Are there cases in which the compiler couldn't figure out what to do?

If the language definition said that . would dereferece
pointers, or that -> would work on structures, the compiler
would have no problem implementing it.

Whether that was true for the original implementation of
C (which, do remember, worked in a environment where the
amount of available memory wouldn't even be enough for a
decent *image* on today's machines), I don't know.

It's not likely to change.
 
S

Suman

Richard Tobin wrote:
[snip]
I think the answer is just that they are different operations so C has
different names for them. a->b is equivalent to (*a).b.
Don't you think that was what I meant, albeit in a roundabout way?
You don't I'll assume for now :)

<i_think_remotely_O(n)T(opic)>
In any case, this fires my curiosity. What if we did have the _same_
operator? Would the compiler not have to extra work?
 
S

Suman

Richard Tobin wrote:
[snip]
I think the answer is just that they are different operations so C has
different names for them. a->b is equivalent to (*a).b.
Don't you think that was what I meant, albeit in a roundabout way?
You don't I'll assume for now :)

<i_think_remotely_O(n)T(opic)>
In any case, this fires my curiosity. What if we did have the _same_
operator? Would the compiler not have to do extra work?
 
L

Lawrence Kirby

Richard Tobin wrote:
[snip]
I think the answer is just that they are different operations so C has
different names for them. a->b is equivalent to (*a).b.
Don't you think that was what I meant, albeit in a roundabout way?
You don't I'll assume for now :)

<i_think_remotely_O(n)T(opic)>
In any case, this fires my curiosity. What if we did have the _same_
operator? Would the compiler not have to do extra work?

Not to any measurable degree. It has to validate the type of the left hand
operand either way.

Lawrence
 
L

Lawrence Kirby

I think the answer is NO, there aren't any reasons why
the distinction exists since the compiler can always
figure it out.
True.

If we would always use '.' and there was a pointer, the
compiler could test if we have instead of a structure,
a pointer to a structure, then generate a dereferencing of
the pointer without much trouble.
True.

The best way to do this is to deprecate '->'

But, helas, this is not going to happen any time soon.

That assumes that this is a sensible and desirable thing to do. It would
make the language syntax marginally simpler, whereas the existing ->
operator highlights the fact that you are using a pointer, which IMO is no
bad thing in C.

Lawrence
 
L

lawrence.jones

Felix Kater 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?

Not anymore. But back in the dark ages, C was much less concerned about
types than it is today and would allow pretty much *anything* as the
left operand of . or ->. In that environment, the compiler couldn't
figure out what to do, so having two different operators was essential.

-Larry Jones

It's no fun to play games with a poor sport. -- Calvin
 
G

Guillaume

Not anymore. But back in the dark ages, C was much less concerned about
types than it is today and would allow pretty much *anything* as the
left operand of . or ->. In that environment, the compiler couldn't
figure out what to do, so having two different operators was essential.

To me, it's still essential syntactically speaking.

Letting the compiler "guess" what you mean is a really, really bad idea
in general. Even when the case seems obvious to you.
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Not anymore. But back in the dark ages, C was much less concerned about
types than it is today and would allow pretty much *anything* as the
left operand of . or ->. In that environment, the compiler couldn't
figure out what to do, so having two different operators was essential.

Nonsense.

Even K&R (1st Edition) admits that the -> notation is 'syntactic sugar' (my
terms). The actual quote from "The C Programming Language" is
"...pointers to structures are so frequently used that the -> notation is
provided as a convenient shorthand."

This, in reference to an example of the use of pointers to structures, which
points out that, given

struct date {
int day;
int month;
int year;
int yearday;
char mon_name[4];
};
and
struct date *pd;
then
pd->year
is exactly the same as
(*pd).year


- --
Lew Pitcher
IT Specialist, Enterprise Data Systems,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFCxBuYagVFX4UWr64RAt02AKCZe0YXskg4oZ+UrPYPXmqtyTHXhgCg5uRk
W0SnNGl1N0ZayPZGkQC+qrs=
=Ckpm
-----END PGP SIGNATURE-----
 
R

Richard Tobin

Guillaume said:
To me, it's still essential syntactically speaking.

Letting the compiler "guess" what you mean is a really, really bad idea
in general. Even when the case seems obvious to you.

So would you favour having different operators for integer and
floating-point addition? Is it a disaster that if foo is a function
pointer you can say foo(1) instead of (*foo)(1)?

Why is determining the action "guessing" in this case but not the
others?

-- Richard
 
G

Guillaume

Richard said:
So would you favour having different operators for integer and
floating-point addition?

Actually, that could be debatable.
When I see so many programmers mixing integers and fp numbers in
expressions without quite knowing what they are doing (and sometimes
wondering why the heck they don't get the results they are expecting),
I'm thinking: why not different operators. At least, that would force
you to have a clear understanding of both what you want and what is
going to happen, without having to read dozens of pages of the standard
and praying that your compiler sticks to it...
Is it a disaster that if foo is a function
pointer you can say foo(1) instead of (*foo)(1)?

You're making a point, but I don't see this as harmful as the "./->"
case. When you see foo(1), you immediately know while reading it
that foo is either a pointer to a function, or a function symbol.
There is no "function type" that you can use in C as a variable;
there are only function pointers. Functions themselves cannot be
C variables, just as you can't "instantiate" a void variable;
only pointers to void are legal.

Since I almost never use a pointer to function without checking
first if it's NULL or not, it's immediately clear what 'foo' is,
without having to browse through hundreds of lines of code...
Why is determining the action "guessing" in this case but not the
others?

In the case of using '.' instead of '->' for pointers to structures,
you loose sight of what the variable type is: is it a pointer to
a structure or a structure? That hinders readability in my opinion.

Then again, I use the Hungarian notation most of the time, so that
would not be that big a deal for me: but I know a lot of programmers
that don't. Then the source code would become hell to read.

High-level languages are meant to be highly readable by you and
by others. Readability should be a big part of programming.
Apparent syntax simplifications do more harm than good in my opinion.
In that particular case, that would tend to make the newer programmers
confuse pointer-types with non-pointer-types. And that would tend
to just plain confuse the more seasoned ones...
 
C

CBFalconer

jacob said:
I think the answer is NO, there aren't any reasons why the
distinction exists since the compiler can always figure it out.

If we would always use '.' and there was a pointer, the compiler
could test if we have instead of a structure, a pointer to a
structure, then generate a dereferencing of the pointer without
much trouble.

It's a convenience, because of the relative operator precedence.
It is easier and clearer to write:

structxp->fieldf
than
(*structxp).fieldf
 
W

Walter Roberson

When I see so many programmers mixing integers and fp numbers in
expressions without quite knowing what they are doing (and sometimes
wondering why the heck they don't get the results they are expecting),
I'm thinking: why not different operators. At least, that would force
you to have a clear understanding of both what you want and what is
going to happen, without having to read dozens of pages of the standard
and praying that your compiler sticks to it...

An alternative would be to not do silent type conversion in expressions --
except perhaps (for convenience) for some forms involving constants.

If there is no operator for int + float then the programmer would
have to put in explicit type casts as necessary, thus forcing the
programmer to pay attention at each substep to the types.


Such a scheme might do interesting things to expressions such as
toupper(HexChar) - 'A' + 10
due to the signed-ness ambiguity of char...
 
C

Chris Torek

Not anymore. But back in the dark ages, C was much less concerned about
types than it is today and would allow pretty much *anything* as the
left operand of . or ->. In that environment, the compiler couldn't
figure out what to do, so having two different operators was essential.

but it might serve to be a bit more detailed.

The "true need" for separate "." and "->" operators went away
sometime around 1978 or 1979, around the time the original K&R
white book came out.

Before then, Dennis' early compilers accepted things like this:

struct { char a, b; };
int x 12345; /* yes, no "=" sign */

main() {
printf("%d is made up of the bytes %d and %d\n", x,
(x.a) & 0377, (x.b) & 0377);
}

(in fact, in an even-earlier version of the compiler, the syntax
was "struct (" rather than "struct {". The syntax above is what
appeared in V6 Unix. I have read V6 code, but never used the V6
C compiler myself.)

Note that we have taken the "a" and "b" elements of a plain
"int", not the "struct" that contains them. The "." operator
works on *any* lvalue, in this early C, and all the structure
member names must be unique -- no other struct can have members
named "a" and "b".

We can (and people did) also write things like:

struct rkreg { unsigned rkcsr, rkdar, rkwc; };
...
/* read disk sector(s) */
0777440->rkdar = addr;
0777440->rkwc = -(bytecount / 2);
0777440->rkcsr = RK_READ | RK_GO;

Note that the "->" operator works on *any* value, not just pointers.

Since this "early C" did not look at the left hand side of the
"." and "->" operators, it really did require different operators
to achieve different effects. These odd aspects of C were fixed
even before the very first C book came out, but -- as with the
"wrong" precedence for the bitwise "&" and "|" operators -- the
historical baggage went along for the ride.
 
A

Anonymous 7843

when accessing the variables in a struct: What's the reason why in C
you have -> and . instead of only . ?

I think it's at least partially historical. Most other languages of
the time (mid seventies) were making the distinction between pointing
and membership, perhaps less for utilitarian reasons and more because
there was a perception (at the time) that pointers were a difficult
concept for computer science students to grasp. Having a distinct
syntax (one which actually has a "pointy" symbol) may have been helpful
in that area.
 
E

Eric Sosman

Walter said:
If there is no operator for int + float then the programmer would
have to put in explicit type casts as necessary, thus forcing the
programmer to pay attention at each substep to the types.

FORTRAN II was like this: An expression had to be
entirely integer or entirely floating-point. Assignment
(which FORTRAN didn't think of as an "operator") could
convert types: INT = REAL or REAL = INT were valid, but
INT + REAL was not.

When FORTRAN IV came along and allowed mixed expressions
my initial reaction was "Why? We've been getting along
fine without them." It didn't take me long to change my
mind, though, and I would not want to return to the old days.
Such a scheme might do interesting things to expressions such as
toupper(HexChar) - 'A' + 10
due to the signed-ness ambiguity of char...

The signedness of `char' does not affect this expression
because the three operands are all of type `int'. The type
of `HexChar' is not shown, but if its value is in fact one of
the letters 'a' through 'f' or 'A' through 'F' then that value
is positive even if `char' is signed.

(Note that the expression is not a bulletproof way to
derive a hex digit's value from a letter, even if the letter
is known to be valid. The codes for these letters need not
be ascending, nor even adjacent. I know of no encoding where
they aren't -- but at least one encoding where 'A' + 25 != 'Z'
exists and is in current use, so there's at least a potential
for unpleasant surprises.)
 

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
473,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top