Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Why does C even have two member selection operators?

Anyway it means you can't cut and paste code from one place to another without changing '.' to '->' or vice-versa.




A '->' is always a runtime indirection involving an extra memory access, while a '.' is always resolved into a single offset at compile time.

E.g. a:

int x = a->b->c->d;

means there's 3 memory accesses, while

int x = a.b.c.d;

means there's one memory access for the whole expression.

Also consider this:

int x = a->b.c->d;

I can immediately see where pointer indirections are happening.

...unless you're in C++ of course which messed up this simple rule when references were added to the language.


>A '->' is always a runtime indirection

It's not true if the compiler can figure out that the left side is a constant, consider:

    struct foo { int a; };
    struct foo z = { 7 };
    struct foo *const p = &z;
Then in z->a, no indirection is necessary. GCC -O2 makes this:

    int fred() { return p->a; }

    fred:
        movl    z(%rip), %eax
        ret

    p:
        .quad   z

    z:
        .long   7


That's (usually) only true for the very first '->' in a chain and as you said, depends on the compiler figuring out if the pointer indirection can be resolved at compile time.

A chain of '.' on the other hand is always guaranteed to be resolved into a single offset at compile time.


> Why does C even have a two member selection operators?

Because using `(*ptr).member` everywhere is annoying. There's plenty of times you want or need to have direct access to a member rather than always dereferencing a pointer.


It's too bad C's pointer-deref operator is prefix instead of postfix. In Pascal it's ^ so you write ptr^.member and there's no special -> operator. Even better, declarations and expressions would read intuitively left-to-right instead of spiraling out through stars on the left and brackets on the right.


In C you can use [0] for postfix pointer dereferencing.


Alas, that's clumsy, and for declarations not possible. I have used it in expressions at times.

Here's a variation that seems plausible: make postfix p^ be like C's p[0], and infix p^i like C's p[i]. (With a tighter binding for ^ than C has.)


So that's where the lens notation comes from...

https://github.com/ekmett/lens/wiki/Examples

> ("hello","world")^._2


ptr.member should work here- I mean the compiler knows the left side is a pointer, so it should automatically dereference it.


C was practically a portable assembler when it was designed, and it was likely helpful for performance reasoning that all indirections were clearly visible.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: