1. 25
  1.  

    1. 15

      The C’s prefix syntax has been used for so long that .* looks weird, but a postfix operator is the right place for a dereference. It chains nicely, and if you squint, it’s consistent with field access syntax that is also a form of dereference.

      1. 11

        The “.” is weird, though — it makes it look like a struct field. Pascal’s postfix “^” operator is clearer.

        (An article explaining pointer dereferencing seems maybe a bit basic for lobste.rs…?)

        1. 6

          Think about it as just “field access, but with a wildcard”

          Instead of .field you do .* which matches all fields, and suddenly it feels more natural than another “special syntax”

          1. 3

            According to this mental model, .? should return arbitrary one field :D

            1. 2

              It should return all fields whose names are one character :)

          2. 2

            I was actually coming here to say that I really appreciate the well-written, intro-level post. I’ve been programming for almost 15 years professionally but I’ve spent all that time in high-level languages and am still really “getting” pointers. Programming is such an enormous field, there’s always something to learn. 🙂

            1. 1

              Do you feel the same way about calling methods with .?

              1. 1

                No, a method is an element of the pointed-to struct, just like a field access. It’s the use of “.” without any field that seems weird to me.

                1. 2

                  Funny, I quite like it. If I ever create a language of my own I’d probably use that.

                  Maybe it is just from being exposed to Go, with it’s “ptr.(type)” and “ptr.(int)” forms for type switch and assertion which make it seem a bit more comfortable.

            2. 6

              Adding to snej’s comment, in Pascal you write p^ to dereference a pointer and r.f to select a field from a record. If you have a pointer to a record, you can write pr^.f. It’s simple, orthogonal and logical.

              The C language made the ergonomic mistake of using a prefix operator to dereference a pointer (*p). To get a field from a struct pointer, this means you write (*rp).f. That sucks so badly that C has a short-form for this: you can write rp->f instead. It’s an over-complicated bad design.

              Zig collapses the C operators . and -> into a single . operator, and replaces C’s one-character prefix pointer-deref operator * with a two-character postfix operator .*. This is a bit more ergonomic than C, but it’s still a bad design, when compared to Pascal.

              1. 4

                Not to defend prefix dereference, but it’s not like you can’t fix C’s mistakes. Rust supports rp.f just fine by auto-dereferencing until it finds the right type and doesn’t need -> or an explicit deref for trivial accesses

                The order of operations issue still exists, but to a much lesser extent.

                1. 3

                  Huh, I wonder if that Pascal design is why the Haskell lens packages uses ^. as an alias for view. As in, record ^. foo . bar . baz = view (foo . bar . baz) record accesses a value nested through several layers of record.

                  1. 3

                    BCPL has two forms of the dereference operator, prefix unary and infix binary. The latter does double duty for structure access and array indexing.

                    C           BCPL
                    *ptr        !ptr
                    ptr->field  ptr!field
                    ptr[n]      ptr!n
                    

                    In pre-K&R C before the type safety of structures was improved, C’s ptr->field was a lot more like BCPL’s ptr!field, but with a nicer way to declare the field offsets and types. But like BCPL, the left hand operand could be anything. For example, in the 6th edition kernel there are expressions (after macro expansion) like 0177560->integ for accessing hardware registers.

                    Late 1960s versions of BCPL had the rather awkward lv and rv operators for taking addresses and indirection; they became @ and ! in the early 1970s. https://www.softwarepreservation.org/projects/BCPL/

                    The lv / rv thing was from Strachey’s idea of lvalues and rvalues. The CPL project seems to have struggled a lot with references, list processing, and record types. The whole effort fell apart before they worked out a solution.

                    Dunno how much users in the USA kept up with revisions to BCPL after Martin Richards returned from Cambridge Massachusetts to Cambridge England.

                  2. 2

                    I like how Nim uses p[] for dereference. It’s like indexing an array, but without an index.

                  3. 5

                    I’m a big fan of the .* syntax. It instantly clicked for me and now I want it in every other language with pointers.