

Ask HN: In C, why is the * operator both reference and type casting? - blintson

This is something that's been bothering me since I've learned C. Take the following code:<p><pre><code>  *(int*)pointer_param = bar;
</code></pre>
In the above code the two * operators do two different things:<p>1. Converts variable type to pointer.<p>2. References value found at address.<p>What was the historical reason for using the * operator for both things? Memory? Is it easier to write a compiler for? Is there something I'm missing?<p>EDIT:Code, also, It seems like a lisp version would be much easier to write a compiler for and to write; i.e.<p>(define (address-ref (float_pointer_cast pointer_param))
 bar)<p>Is there some reason that the C-version is easier to write a compiler for/optimize than the lisp?
======
tmsh
I imagine the rationale was something like: how do we indicate that types are
references to memory? Let's be concise and use the asterisk after the type of
the memory.

How do we dereference an address? Since it only makes sense that types with an
asterisk will be dereferenced, let's use an asterisk like we did in the type
declaration. There, we have uniformity.

Oh wait, f-. What about if we want the address of something on the stack? Oh,
maybe use the ampersand, and then that returns a pointer just like a pointer
to something on the heap. Awesome! Let's even extend that ampersand to return
the address of anything. Dereferenced pointers. What have you.

And yet, it's not completely symmetrical. Hence, pointers not being completely
intuitive.

In addition, the ampersand as 'reference' is another completely unrelated
syntax convenience. Which of course makes the language even slightly less
symmetrical.

But, once you understand exactly what it's doing -- and your mind will adapt
until it seems completely intuitive -- it is quite concise.

But the trick is that it's not concise like s-expressions. There's no clear
symmetry. A lot of C (and even more C++) is simply syntax.

------
Locke1689
The second * has nothing to do with type-casting -- it is part of the type
identification. The operator performing the typecast is the pair of
parentheses.

Consider: int and int * are two different types. So typecasting to int when
you really mean int * is completely different.

------
dasht
The * in the parentheses is part of type name and it indicates that the type
being named is the sort of type to which it makes sense to apply the run-time
* operator.

------
cperciva
Substitute the obvious character for $%^& below -- I couldn't figure out how
to convince HN that I wasn't just delimiting italics.

 _What was the historical reason for using the $%^ & operator for both
things?_

I think the argument was that it allows you to say "foo is a pointer to an
integer" == (int $%^&) foo == int ($%^& foo) == "that which is pointed to by
foo, is an integer".

------
jey
(Mentally replace all ^s with asterisks in the following:)

I don't understand your C code. What is "(int foo^)" supposed to do? It looks
almost like a cast, but "int foo" isn't a valid type in C. Maybe "(struct
foo^)" or "(int^)"?

~~~
blintson
I wrote that wrong, my bad. I was copying from a call-by-value example from
memory. Changed the following:

    
    
      *(int *foo)pointer_param /*changed to*/  *(int*)pointer_param = bar

