<p>In some C-based languages (including C/C++ themselves and Rust), taking pointers/references and dereferencing is done with prefix operators <code>&amp;</code> and <code>*</code>. I've noticed that this often entails extraneous parentheses when the (de-)referenced expression is passed to a postfix operator, such as array subscript (<code>[]</code>) or attribute resolution (<code>.</code>/<code>::</code>).</p>
<p>I believe using postfix operators for (de-)referencing could solve this issue (similar to Rust's postfix <code>.await</code>). However, simply reusing the same operators in a postfix form results in syntactic ambiguities. For instance, is <code>a*-b</code> multiplication or subtraction?</p>
<p>My question is, what other syntax do such operations have in other languages? Specifically, I'm interested in approaches that avoid ambiguity and, preferably, also preserve some familiarity to C programmers.</p>

<syntax><operators><pointers><references>
Common postfix representations of pointer/reference operations
CC BY-SA 4.0
2023-08-13T20:49:33.300Z
[“What are some possible syntaxes?” questions are off-topic.](https://langdev.meta.stackexchange.com/q/578) You could narrow this question by making it explicitly about syntaxes used in existing, popular languages, though.
Alexis King
CC BY-SA 4.0
2023-08-13T20:53:22.357Z
@AlexisKing okay, thanks. Although it's already a bit more narrow, since I'm asking for specifically ones preserving C-likeness. But I'll edit regardless
abel1502
CC BY-SA 4.0
2023-08-13T20:55:16.223Z
Thanks! We’ve been trying to move away from open-ended language design questions on this site. See also [Moving towards more focused language design questions](https://langdev.meta.stackexchange.com/q/543).
Alexis King
CC BY-SA 4.0
2023-08-14T03:46:46.143Z
"*this often entails extraneous parentheses*" — a common trick in C is to remember that `a[b]` is `*⁠(a+b)`, which is `*⁠(b+a)`, which is `b[a]`, so rather than `(&x)[y]` one can write `y[&x]`.
Ray Butterworth
CC BY-SA 4.0
2023-08-15T17:40:42.423Z
@RayButterworth -- you can, and then 90% of programmers reading your code will go "huh? y isn't an array..."
occipita
<p>A few more examples.</p>
<p><strong>Pascal</strong></p>
<pre class="lang-pascal prettyprint-override"><code>program pointer_example;  
var i  : Integer;  
    ip : ^Integer;     (* Pointer to integer; ^ is prefix *)
begin
    i := 0;
    (* Neither ISO 7185 Standard Pascal nor ISO 10206 Extended
       Pascal describe a way to get a pointer to a variable, but
       this is a common extension. See comments below. *)
    ip := @i;          (* Get a pointer to an integer; @ is prefix *)
    ip^ := ip^ xor 1;  (* Dereference is a postfix operator. *)
                       (* Also note that ^ is not used for any other purpose. *)
end.
</code></pre>
<p><strong>Fortran</strong></p>
<pre><code>program pointerExample
implicit none
   integer, pointer :: p1  ! p1 is a pointer to integer
   integer, target :: t1   ! t1 is an integer target

   ! You can only take the address of a variable that has the &quot;target&quot;
   ! attribute. Fortran has very strict aliasing rules, and this signals
   ! that the variable may be aliased.
   !
   ! This is kind of the opposite of the (now deprecated) &quot;register&quot;
   ! keyword in C, which is a signal that you cannot take the address
   ! of it, and it will never be the alias of another variable.

   t1 = 1
   p1=&gt;t1                  ! p1 points to t1
   p1 = 2                  ! Fortran has no pointer arithmetic, so there
                           ! is no need for special &quot;dereference&quot; syntax.
end program pointerExample
</code></pre>
<p><strong>BLISS</strong></p>
<pre><code>! BLISS is unusual in that the name of a variable denotes
! a pointer to it. If this sounds weird to you, consider that in
! C, the name of an array denotes a pointer to its first member.
!
! Note that BLISS only really has one &quot;type&quot;: the machine word.
MODULE POINTERS (MAIN = CTRL) =
BEGIN
FORWARD ROUTINE
    TEST;
ROUTINE TEST =
    BEGIN
        LOCAL
            X,
            Y;
        ! This assigns 1 to the variable X.
        X = 1;
        ! This assigns the address of the variable X to the
        ! variable Y, with no explicit &quot;reference&quot; operator.
        Y = X;
        ! If you want to assign the value in X to the variable Y,
        ! you need to explicitly dereference X.
        X = .Y;
        ! Dereference on the lhs means assigning through a pointer.
        ! Store 2 in the memory location stored in Y.
        .Y = 2;
    END;
ELUDOM
</code></pre>

CC BY-SA 4.0
2023-08-14T05:53:59.517Z
2023-08-16T01:03:04.990Z
2023-08-16T01:03:04.990Z
Pseudonym
CC BY-SA 4.0
2023-08-15T17:48:51.017Z
Note that the `@` operator is not standard Pascal, but a common extension.  Some Pascal implementations either don't support the operation (only allowing pointers to come into existence through an invocation of `new`) or handle it differently (e.g. Solaris's Pascal compiler has a psuedo-function called `addr` that achieves the same thing).
occipita
CC BY-SA 4.0
2023-08-16T00:58:58.297Z
Thank you for that; I will edit accordingly.
Pseudonym
<p>This is almost certainly why the <code>-&gt;</code> operator exists in C and C++, since <a href="https://stackoverflow.com/a/69045601"><code>a-&gt;b</code> is merely syntactic sugar for <code>(*a).b</code></a>*.</p>
<p>C++ doesn't have an equivalent postfix for overloaded subscript or call, but you could easily create something like <code>a-&gt;[index]</code> in your own language. You could also allow the operator to be chained for more layers of indirection (so <code>(**a).b == a-&gt;-&gt;b</code>), although that may be pushing it.</p>
<p>Alternatively, you could make dereferencing itself postfix. The main downsides are deviation from the norm and potentially slightly more difficulty parsing (<code>a*</code> and <code>a&amp;</code> look like the beginning of a multiplication and bitwise AND respectively, though <code>a*.</code>, <code>a&amp;,</code>, <code>a&amp;)</code>, <code>a*;</code>, and probably all other valid syntax using dereference are obviously not operations).</p>
<p>* ...<a href="https://stackoverflow.com/a/69045600">except for this special case where a C++ class provides 2 semantically different overloads</a>, but that kind of garbage is like <code>#define true false</code></p>

CC BY-SA 4.0
2023-08-14T05:03:04.173Z
2023-08-14T05:09:31.270Z
2023-08-14T05:09:31.270Z
tarzh
<p>Rust has a postfix syntax for acquiring shared and mutable references ─ it's nothing special, though. You just call the <code>.borrow()</code> or <code>.borrow_mut()</code> method, as long as the <a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html" rel="nofollow noreferrer"><code>Borrow</code></a> or <a href="https://doc.rust-lang.org/std/borrow/trait.BorrowMut.html" rel="nofollow noreferrer"><code>BorrowMut</code></a> trait is in scope, respectively.</p>
<p>Example (<a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=1e67f1b32da601c03df571b3a7bddefb" rel="nofollow noreferrer">playground link</a>):</p>
<pre class="lang-rust prettyprint-override"><code>struct Foo;
fn accepts_shared_ref(_x: &amp;Foo) {}
fn accepts_mut_ref(_x: &amp;mut Foo) {}

fn main() {
    use std::borrow::{Borrow, BorrowMut};
    
    let mut x = Foo;
    accepts_shared_ref(x.borrow());
    accepts_mut_ref(x.borrow_mut());
}
</code></pre>
<p>For dereferencing, there are also the <a href="https://doc.rust-lang.org/std/ops/trait.Deref.html" rel="nofollow noreferrer"><code>.deref()</code></a> and <a href="https://doc.rust-lang.org/std/ops/trait.DerefMut.html" rel="nofollow noreferrer"><code>.deref_mut()</code></a> methods, but these don't have a blanket implementation for every type because that would violate the language's ownership model.</p>

CC BY-SA 4.0
2023-08-13T21:29:07.370Z
2023-08-13T21:29:07.370Z
kaya3
CC BY-SA 4.0
2023-08-13T21:35:42.320Z
That's a good point, but I feel that references are significant enough in my language to deserve concise syntax. Rust still has `&`, and it's subject to the flaws I've described. I'd like to adress them from the start in my language, rather than through a retrofiited alternative in the standard library
abel1502
<p>Pascal uses postfix <code>↑</code> or <code>^</code> for dereference.</p>
<p>As I understand it, standard Pascal doesn't have an address operator (you can only form pointers to dynamically allocated objects).  However some implementations provide this as an extension, using prefix <code>@</code>.</p>
<p>Confusingly, ISO Pascal apparently allows <code>@</code> as an alternative token for <code>↑</code>, on an implementation-defined basis.  If so then postfix <code>@</code> would also be a dereference.</p>

CC BY-SA 4.0
2023-08-14T05:40:48.513Z
2023-08-14T05:40:48.513Z
Nate Eldredge
# Common postfix representations of pointer/reference operations
Posted by: username_0 on 2023-08-13
In some C-based languages (including C/C++ themselves and Rust), taking pointers/references and dereferencing is done with prefix operators `&` and `*`. I've noticed that this often entails extraneous parentheses when the (de-)referenced expression is passed to a postfix operator, such as array subscript (`[]`) or attribute resolution (`.`/`::`).

I believe using postfix operators for (de-)referencing could solve this issue (similar to Rust's postfix `.await`). However, simply reusing the same operators in a postfix form results in syntactic ambiguities. For instance, is `a*-b` multiplication or subtraction?

My question is, what other syntax do such operations have in other languages? Specifically, I'm interested in approaches that avoid ambiguity and, preferably, also preserve some familiarity to C programmers.
**Tags:** syntax operators pointers references
> **Comments:**
> **username_1**: [“What are some possible syntaxes?” questions are off-topic.](https://langdev.meta.stackexchange.com/q/578) You could narrow this question by making it explicitly about syntaxes used in existing, popular languages, though.  
> **username_0**: @AlexisKing okay, thanks. Although it's already a bit more narrow, since I'm asking for specifically ones preserving C-likeness. But I'll edit regardless  
> **username_1**: Thanks! We’ve been trying to move away from open-ended language design questions on this site. See also [Moving towards more focused language design questions](https://langdev.meta.stackexchange.com/q/543).  
> **username_2**: "*this often entails extraneous parentheses*" — a common trick in C is to remember that `a[b]` is `*⁠(a+b)`, which is `*⁠(b+a)`, which is `b[a]`, so rather than `(&x)[y]` one can write `y[&x]`.  
> **username_3**: @RayButterworth -- you can, and then 90% of programmers reading your code will go "huh? y isn't an array..."  
---
## 4 answers
### Answer by username_4 on 2023-08-14. Score: 4
A few more examples.
Pascal
program pointer_example;  
var i  : Integer;  
    ip : ^Integer;     (* Pointer to integer; ^ is prefix *)
begin
    i := 0;
    (* Neither ISO 7185 Standard Pascal nor ISO 10206 Extended
       Pascal describe a way to get a pointer to a variable, but
       this is a common extension. See comments below. *)
    ip := @i;          (* Get a pointer to an integer; @ is prefix *)
    ip^ := ip^ xor 1;  (* Dereference is a postfix operator. *)
                       (* Also note that ^ is not used for any other purpose. *)
end.

Fortran
program pointerExample
implicit none
   integer, pointer :: p1  ! p1 is a pointer to integer
   integer, target :: t1   ! t1 is an integer target

   ! You can only take the address of a variable that has the "target"
   ! attribute. Fortran has very strict aliasing rules, and this signals
   ! that the variable may be aliased.
   !
   ! This is kind of the opposite of the (now deprecated) "register"
   ! keyword in C, which is a signal that you cannot take the address
   ! of it, and it will never be the alias of another variable.

   t1 = 1
   p1=>t1                  ! p1 points to t1
   p1 = 2                  ! Fortran has no pointer arithmetic, so there
                           ! is no need for special "dereference" syntax.
end program pointerExample

BLISS
! BLISS is unusual in that the name of a variable denotes
! a pointer to it. If this sounds weird to you, consider that in
! C, the name of an array denotes a pointer to its first member.
!
! Note that BLISS only really has one "type": the machine word.
MODULE POINTERS (MAIN = CTRL) =
BEGIN
FORWARD ROUTINE
    TEST;
ROUTINE TEST =
    BEGIN
        LOCAL
            X,
            Y;
        ! This assigns 1 to the variable X.
        X = 1;
        ! This assigns the address of the variable X to the
        ! variable Y, with no explicit "reference" operator.
        Y = X;
        ! If you want to assign the value in X to the variable Y,
        ! you need to explicitly dereference X.
        X = .Y;
        ! Dereference on the lhs means assigning through a pointer.
        ! Store 2 in the memory location stored in Y.
        .Y = 2;
    END;
ELUDOM
> **Comments:**
> **username_3** (2023-08-15): Note that the `@` operator is not standard Pascal, but a common extension.  Some Pascal implementations either don't support the operation (only allowing pointers to come into existence through an invocation of `new`) or handle it differently (e.g. Solaris's Pascal compiler has a psuedo-function called `addr` that achieves the same thing).  
> **username_4** (2023-08-16): Thank you for that; I will edit accordingly.  
---
### Answer by username_5 on 2023-08-14. Score: 3
This is almost certainly why the `->` operator exists in C and C++, since [`a->b` is merely syntactic sugar for `(*a).b`](https://stackoverflow.com/a/69045601)\*.

C++ doesn't have an equivalent postfix for overloaded subscript or call, but you could easily create something like `a->[index]` in your own language. You could also allow the operator to be chained for more layers of indirection (so `(**a).b == a->->b`), although that may be pushing it.

Alternatively, you could make dereferencing itself postfix. The main downsides are deviation from the norm and potentially slightly more difficulty parsing (`a*` and `a&` look like the beginning of a multiplication and bitwise AND respectively, though `a*.`, `a&,`, `a&)`, `a*;`, and probably all other valid syntax using dereference are obviously not operations).

\* ...[except for this special case where a C++ class provides 2 semantically different overloads](https://stackoverflow.com/a/69045600), but that kind of garbage is like `#define true false`
---
### Answer by username_6 on 2023-08-13. Score: 2
Rust has a postfix syntax for acquiring shared and mutable references ─ it's nothing special, though. You just call the .borrow() or .borrow_mut() method, as long as the Borrow or BorrowMut trait is in scope, respectively.
Example (playground link):
struct Foo;
fn accepts_shared_ref(_x: &Foo) {}
fn accepts_mut_ref(_x: &mut Foo) {}

fn main() {
    use std::borrow::{Borrow, BorrowMut};
    
    let mut x = Foo;
    accepts_shared_ref(x.borrow());
    accepts_mut_ref(x.borrow_mut());
}

For dereferencing, there are also the .deref() and .deref_mut() methods, but these don't have a blanket implementation for every type because that would violate the language's ownership model.
> **Comments:**
> **username_0** (2023-08-13): That's a good point, but I feel that references are significant enough in my language to deserve concise syntax. Rust still has `&`, and it's subject to the flaws I've described. I'd like to adress them from the start in my language, rather than through a retrofiited alternative in the standard library  
---
### Answer by username_7 on 2023-08-14. Score: 2
Pascal uses postfix `↑` or `^` for dereference.

As I understand it, standard Pascal doesn't have an address operator (you can only form pointers to dynamically allocated objects). However some implementations provide this as an extension, using prefix `@`.

Confusingly, ISO Pascal apparently allows `@` as an alternative token for `↑`, on an implementation-defined basis. If so then postfix `@` would also be a dereference.
---
