Why does C have a distinction between -> and .?

2020-01-25 06:54发布

OK, this is of no serious consequence, but it's been bugging me for a while: Is there a reason for the distinction between the -> and . operators?

Of course, the current rule is that . acts on a struct, and -> acts on a pointer-to-struct (or union). But here's how it works in practice. Let s be a struct incuding an element x, and let ps be a pointer to a struct of the same form.

If you write

s->x

the compiler will spit out a warning in the way of

You meant s.x. Please retype that and recompile.

If you write

ps.x

the compiler will spit out a warning in the way of

You meant ps->x. Please retype that and recompile.

Because the compiler knows the type of both s and ps at compile time, it has all the information it needs to interpret what the correct operator would be. I suspect that this isn't like other warnings (like a missing semicolon), in that there is no ambiguity about the correct fix.

So here's a hypothetical proposal to the C1x standards committee (that would never be considered, because the ISO is on a conservative streak):

Given the expression lhs.rhs, if lhs is a struct or union type, then the expression shall refer to the element of lhs named rhs. If lhs is of type pointer-to-struct or -union, then this shall be interpreted as (*lhs).rhs.

This would certainly save us all time, and make it easier for people to learn C [and I've taught enough C to say with authority that learners find the -> thing to be either confusing or annoying.]

There's even precedent, where C does a handful of similar things. E.g., for implementation reasons, function declarations are always cast to pointer-to-function, so f(x,y) and (*f)(x,y) will both work regardless of whether f was declared as a function or a pointer to function.

So, my question: what's wrong with this proposal? Can you think of examples where there would be fatal ambiguity between ps.x and s.x, or why keeping the mandatory distinction is otherwise useful?

标签: c struct
7条回答
Juvenile、少年°
2楼-- · 2020-01-25 07:29

I don't think there's anything crazy about what you've said. Using . for pointers to structs would work.

However, I like the fact that pointers to structs and structs are treated differently.

It gives some context about operations and clues as to what might be expensive.

Consider this snippet, imagine that it's in the middle of a reasonably large function.

s.c = 99;
f(s);

assert(s.c == 99);

Currently I can tell that s is a struct. I know that it's going to be copied in its entirety for the call to f. I also know that that assert can't fire.

If using . with pointers to struct were allowed, I wouldn't know any of that and the assert might fire, f might set s.c (err s->c) to something else.

The other downside is that it would reduce compatibility with C++. C++ allows -> to be overloaded by classes so that classes can be 'like' pointers. It's important that . and -> behave differently. "New" C code that used . with pointers to structs would no probably not be acceptable as C++ code any more.

查看更多
登录 后发表回答