Why does the arrow (->) operator in C exist?

14 points by spc476


wrs

And BTW, that global namespace for struct members is why old Unix style (still used today) prefixes all the member names. All the struct tm members start with tm_, and so forth.

fanf

This doesn’t really answer the question.

In order to dereference a pointer, the * operator needs to know the type of its operand. So C of that era had enough type information to know whether a variable was a pointer or not, and what type it pointed to.

So (in theory) it also had enough type information to know whether . should offset (if the left operand is a struct type) or indirect (otherwise). But in practice it didn’t pay attention to types in that manner, because of the way it gradually evolved from BCPL via B and NB.

This weirdness is also (weirdly) related to C’s weird treatment of arrays that decay to pointers. In BCPL, when you declare v[10] you get 10 slots for the array elements but also a -1th slot containing pointer to the start of the array (ie, v == &v + 1). So v!5 always treats v as a pointer to an array, and offsets the contents of the variable v (ie, its rvalue not its lvalue) by 5 words before fetching a value. In C there’s magic that avoids creating an explicit slot for the address of the array by magically making v evaluate to &v (ie, its rvalue is its lvalue) so that v[5] doesn’t waste a word for the indirection.

C could have done a similar thing for structs, so that s magically evaluates to &s such that s->m works when s is not a pointer. Or rather it would have used . for the indirection operator instead of -> because the decay-to-pointer would have made the non-dereferencing . redundant.

So the mystery is why C treats arrays and structs differently.

bitshift

In 2026 this would be a bonkers language design, but I think the individual steps make sense in context. The original behavior of -> must have made the compiler implementation simpler or something? TIL, thanks for sharing!

Also, choice quote:

Needless to say, things like this could easily result in memory overrun, but the language did not concern itself with such matters.