News for hackers. Stuff that matters.
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @08:02AM (#37830994)
> Otherwise "(*x).y" would have been needed, instead of "x->y". With a postfix "*", that would have been "x*.y", and "->", would not have been needed.

I mean technically the compiler could just have been less stupid and made `.` auto-deref, it’s not like C has operator overloading so the LHS is either a struct or a pointer, not both.

Re:C uses "&" for the address-operator because 'ampersand so... by adrian_b on Tuesday October 10, 2023 @08:16AM (#37831098)
It is not that simple, because in C you may chain a great number of prefix and postfix operators.

It is frequent to have multiple "*", "[]", "." and "->".

Now you have the simple rule of executing first the postfix operators from left to right, then the prefix operators from right to left.

If some special rules had to be invented to avoid writing the parentheses in "(*x).y", after adding several "*", "[]" and "." it would become impossible to understand the right evaluation order.

When all of "*", "[]" and "." are postfix, they are just executed in order from left to right, which is easy to understand.

While sometimes auto-dereferencing a pointer would be convenient, in C you want frequently to get the value of a link, or to do pointer arithmetic. With auto-dereferencing, some new ways of using an "address of" operator would have to be invented, which are unlikely to be more simple than the current rules.

Like I have said, the 2 languages that have introduced the concept of pointers were Euler, with explicit dereferencing, and CPL, with implicit auto-dereferencing.

Both are valid ways to design a programming language, but in both case a lot of rules must be added to cover all the use cases, which would have to be more complex in the languages with auto-dereferencing, so these languages usually solve this problem lazily, by just prohibiting some uses, e.g. by prohibiting pointer arithmetic.

Re:C uses "&" for the address-operator because 'ampersand so... by tsimionescu on Tuesday October 10, 2023 @08:29AM (#37831203)
I believe GP means that "a.b" should be enough for pointers as well, you don't need "a->b" or "(*a).b". It's not like pointers can have fields in C, so the meaning would have been unambiguous.
Re:C uses "&" for the address-operator because 'ampersand so... by adrian_b on Tuesday October 10, 2023 @08:43AM (#37831320)
Sorry, I had posted a partial reply before finishing writing the complete one.

As I have written above, a language with implicit dereferencing needs additional syntactic means for denoting the cases when the values of the pointers are needed, e.g. for doing pointer arithmetic, which is frequent in C.

If dereferencing would have been made implicit, that would have required a large number of changes in the language. C++ has introduced pointers with implicit dereferencing, i.e. what C++ calls references, but due to the fact that the other syntax changes that are needed have not been made, because they would break compatibility, the C++ references can replace C pointers only in a subset of their uses.

Re:C uses "&" for the address-operator because 'ampersand so... by dataflow on Tuesday October 10, 2023 @08:53AM (#37831431)
> If dereferencing would have been made implicit

You're misunderstanding the comment. They aren't asking for implicit derefs. They're asking for explicit derefs, using * or . instead of * or ->

Re:C uses "&" for the address-operator because 'ampersand so... by psd1 on Tuesday October 10, 2023 @09:12AM (#37831619)
Your and GP's make no sense unless the reader knows that * is a markdown directive and infers where you typed them.

Which is ironic when discussing overloading!

Re:C uses "&" for the address-operator because 'ampersand so... by dataflow on Tuesday October 10, 2023 @09:16AM (#37831652)
In confused, where in my comment does the Markdown syntax come into play? You're not seeing italics or backslashes are you?
Re:C uses "&" for the address-operator because 'ampersand so... by psd1 on Tuesday October 10, 2023 @05:03PM (#37837437)
I see now - Hacki renders italics, but the browser doesn't.

Excuse my confusion, this possibility didn't occur to me.

Re:C uses "&" for the address-operator because 'ampersand so... by fanf2 on Tuesday October 10, 2023 @09:26AM (#37831796)
Hacker News does not use Markdown.
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @09:58AM (#37832178)
While that’s technically true, it does use a severely cut down version thereof which is worse in every way: it only supports paragraphs, code blocks, and emphasis so the ability to format is extremely limited but the emphasis can still screw you over, which requires an explicit preview (or posting) to notice.

And I think escaping emphasis was only introduced somewhat recently? I do remember that for the longest time you basically had to trick HN into not breaking your comments by using a different character in stead.

Re:C uses "&" for the address-operator because 'ampersand so... by OJFord on Tuesday October 10, 2023 @09:59AM (#37832197)
No, but it does use:

    *
for italics, which sometimes causes a comment to go haywire because someone uses it to reference a footnote or otherwise drops it in mid-sentence, with a matching closing one, not intending italics.

(Up-thread I think it probably was like that when they commented, but has since been fixed.)

Re:C uses "&" for the address-operator because 'ampersand so... by wruza on Tuesday October 10, 2023 @04:20PM (#37836944)
Btw, you can now(?) escape * in a paragraph with \*.
Re:C uses "&" for the address-operator because 'ampersand so... by OJFord on Tuesday October 10, 2023 @06:54PM (#37838816)
Yes, it's also automatic in some cases - originally my comment had an attempt at a joke example of it, but it was caught and didn't work. It was definitely improved relatively recently.
Re:C uses "&" for the address-operator because 'ampersand so... by adrian_b on Tuesday October 10, 2023 @09:16AM (#37831657)
With explicit derefs, if "*x.y" is taken to mean "(*x).y", then which is the meaning of "****x1.x2[7].x3.x4[9].x5"?

> "a.b" should be enough for pointers as well,

I have interpreted this to mean implicit deref, as there is no "*" (could be a formatting problem).

Re:C uses "&" for the address-operator because 'ampersand so... by dataflow on Tuesday October 10, 2023 @09:18AM (#37831684)
I think you're still misunderstanding the proposal. What are the types of your variables? This discussion makes no sense without type information. We're defining the meaning of . for pointers here. You seem to be misunderstanding the proposal as being purely a textual transformation that ignores types?

The proposal is literally: "If you see . and the left operand is a pointer, pretend the . was -> instead, because otherwise the code is already invalid."

Re:C uses "&" for the address-operator because 'ampersand so... by adrian_b on Tuesday October 10, 2023 @10:06AM (#37832289)
OK, I believe that you are right and if implicit dereferencing had been done only when this is the only interpretation that leads to a valid expression, then "->" would not have been necessary.

However, I assume that this would have been a too complex solution for compilers that had to work in a few tens of kilobytes of memory, while a postfix "*", as already used a decade before C, would have been a trivial solution.

Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @10:22AM (#37832497)
> However, I assume that this would have been a too complex solution for compilers that had to work in a few tens of kilobytes of memory

It's literally the same complexity as the type checking compilers already do to tell you that your `.` does not work because the LHS is a pointer not a struct.

Re:C uses "&" for the address-operator because 'ampersand so... by adrian_b on Wednesday October 11, 2023 @01:26AM (#37841236)
It is not the same complexity, because syntax checking stops immediately at an error.

To determine if implicit dereferencing may be applied, more analysis has to be done, because there it may be not only a pointer to a structure, but a pointer to a pointer to a structure and so on, so multiple implicit dereferencing may be needed to obtain a valid expression.

However I agree that the difference in complexity is not big.

Re:C uses "&" for the address-operator because 'ampersand so... by tsimionescu on Wednesday October 11, 2023 @07:34AM (#37843201)
`a.b` is always valid syntax, there's no way to know if it is a valid C instruction until you resolve the types of a and b. Assigning it valid semantics at that point is exactly as easy as assigning it error semantics.

And no, this would not perform multiple levels of dereferencing anymore than -> does today. You could have literally find&replaced every use of -> with . and every C program would have had the exact same semantics. `struct point **a; a.x = 1` would throw the exact same compilation error that `struct point **a; a->x = 1` throws today. The only difference would be that `struct point *a; a.x = 1;` would write 1 to the field x of the object pointed to by a, instead of throwing an error that says "object of type struct point* has no field named x".

Re:C uses "&" for the address-operator because 'ampersand so... by loup-vaillant on Tuesday October 10, 2023 @09:44AM (#37832018)
> As I have written above, a language with implicit dereferencing needs additional syntactic means for denoting the cases when the values of the pointers are needed, e.g. for doing pointer arithmetic, which is frequent in C.

No it doesn’t. Let’s take this example in valid C:

  struct my_struct { int field };
  struct my_struct  s = { .field = 42 };
  struct my_struct *p = &s;
  printf("direct : %d", s.field);
  printf("pointer: %d", p->field);
  printf("address: %x", p);
What is being proposed here is to make that code valid:

  struct my_struct { int field };
  struct my_struct  s = { .field = 42 };
  struct my_struct *p = &s;
  printf("direct : %d", s.field);
  printf("pointer: %d", p.field); // note the use of a dot here
  printf("address: %x", p);
That is, the naked p is still to be interpreted as what it is: a pointer. It’s just that when we write `a.b`, the language would first check the type of `a`, then dereference it as many times as necessary to get to the underlying struct, and then access its field. For instance:

  struct my_struct { int field };
  struct my_struct    s   = { .field = 42 };
  struct my_struct   *p   = &s;
  struct my_struct  **pp  = &p;
  struct my_struct ***ppp = &pp;
Now let’s see how this automatic indirection would work:

  // All would print the same value
  printf("%d", ppp.field);
  printf("%d", pp .field);
  printf("%d", p  .field);
  printf("%d", s  .field);

  // We can still use explicit indirections
  printf("%d", (*ppp  ).field);
  printf("%d", (**ppp ).field);
  printf("%d", (***ppp).field);
  printf("%d", (*pp   ).field);
  printf("%d", (**pp  ).field);
  printf("%d", (*p    ).field);
We can still get to the actual addresses no problem:

  printf("p: %x", p);
  printf("p: %x", *pp);
  printf("p: %x", **ppp);

  printf("pp: %x", pp);
  printf("pp: %x", *ppp);

  printf("ppp: %x", ppp);
Note that we can play with the & operator too. In valid C we can do this already:

  printf("s.field: %d", s.field);
  printf("s.field: %d", (*&s).field);
  printf("s.field: %d", (**&&s).field);
  printf("s.field: %d", (***&&&s).field);
With automatic indirection the following would be valid too:

  printf("s.field: %d", (&s).field);
  printf("s.field: %d", (&&s).field);
  printf("s.field: %d", (&&&s).field);
---

The kicker here is that the decision on whether an access to a struct member requires dereferencing the pointer or not, is not done at parsing time. It’s done at type checking time. And by the way, in standard C the decision to give you an error or not is already done at type checking time. All this to say, this would be a fairly benign change to compilers.

Now would users get confused? Possibly. With the conflation of pointers and arrays, the following would be equivalent:

  array.field
  (*array).field
  array[0].field
Looks nifty to some perhaps, but some people really meant:

  array[i].field
and forgot to write the index.
Re:C uses "&" for the address-operator because 'ampersand so... by tsimionescu on Tuesday October 10, 2023 @02:01PM (#37835333)
No one here is proposing implicit dereferencing (everywhere), the proposal is just to make the syntax `pointer.field` have the exact same meaning that `pointer->field` has in C today. In all other places, the current syntax and semantics would stay the same.

Since in all situations where pointer->field is valid pointer.valid is an explicit error in C today, this would have been very much doable without major changes in compiler or language implementation.

Of course, at C's level of abstraction, and given the speed limitations of the day, the syntax difference between -> and . may well be argued to have been helpful instead of harmful.

And yes, the same could not be said for C++, where you can implement dereferencing for your own type and get a variable where both `a.b` and `a->b` are valid and have different meanings. This is anyway not a proposal for changing C (or C++) today, merely a "what if" discussion about how C could have been designed differently.

Re:C uses "&" for the address-operator because 'ampersand so... by flohofwoe on Tuesday October 10, 2023 @10:13AM (#37832373)
I really prefer that '.' and '->' remain separate, because it makes it immediately clear when a potentially expensive pointer derefence is happening:

    x = a->b->c->d->e;
...is a pointer-hunting-nightmare / potential cache-miss-galore.

    x = a.b.c.d.e;
...no problem, the whole chain is resolved at compile time into a single offset and results in at most one memory access.

    x = a.b.c->d.e;
...makes it immediately clear that c->d is a pointer access and everything else isn't.

PS: ...and of course C++ messed this simple rule up with the introduction of references.

Re:C uses "&" for the address-operator because 'ampersand so... by nuancebydefault on Tuesday October 10, 2023 @04:43PM (#37837223)
When stepping up from C to C++, it feels ultimately unlogical to use an ampersand to indicate a reference in a declaration, while in an assigment or actual parameter it means address of. Where they out of special chars?
Re:C uses "&" for the address-operator because 'ampersand so... by renox on Tuesday October 10, 2023 @11:03PM (#37840411)
The problem with postfix * for dereferencing is that it would look like a multiplication..

That's why I would have used a postfix @ for dereferencing.

Re:C uses "&" for the address-operator because 'ampersand so... by bluecalm on Tuesday October 10, 2023 @09:31AM (#37831864)
There is something to "explicit is better than implicit" mantra. I appreciate the C way because if I write a.b and it's an error it clarifies what's going on in my head (I now know a is a pointer not an object).
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @09:59AM (#37832196)
> There is something to "explicit is better than implicit" mantra.

I’ll entertain this when C fixes (or at least removes) integer promotion, which is a source of far more bugs and misunderstandings than this could ever be: `.` auto-deref-ing does not actively undermine what little type system C has.

Re:C uses "&" for the address-operator because 'ampersand so... by bluecalm on Tuesday October 10, 2023 @11:09AM (#37833064)
Man, this is completely unrelated problem. Implicit operator overload is just a bad design. Integer promotion has advantages and disadvantages, especially in a language like C where you often use 8bit or 16bit types for memory optimization/alignment reasons.
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @11:40AM (#37833531)
> Man, this is completely unrelated problem.

You assert that you do not want this on grounds of clarity. It is not an unrelated problem to point out that C has numerous obscurity issues significantly worse than this could ever be in the language right now.

> Implicit operator overload is just a bad design.

That's at best a bunch of words arranged nonsensically, and at worst an assertion that you want to remove arithmetic operators from the language?

> Integer promotion has advantages and disadvantages, especially in a language like C where you often use 8bit or 16bit types for memory optimization/alignment reasons.

It's mostly a major actual source of obscurity and bugs.

Re:C uses "&" for the address-operator because 'ampersand so... by bluecalm on Tuesday October 10, 2023 @02:01PM (#37835330)
You are not arguing in good faith but just in case I will point out what you are missing:

1)Implicit operator overload is a bad design in case of pointers and objects because a.b and a->b are both readable, easy to type and short.

2)Integer promotion is not as simple because requiring explicit promotion makes a holy unreadable mess out of your code in the simplest of cases.

2) is demonstrated many times by mongo code lines in Java with all the explicit casts. This is also the reason Python has implicit promotion for its number type. You sacrifice something to get something unlike in 1) where you only lose for no gain what so over.

Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Tuesday October 10, 2023 @03:54PM (#37836647)
> You are not arguing in good faith

You're just not being honest.

> 1)Implicit operator overload is a bad design in case of pointers and objects because a.b and a->b are both readable, easy to type and short.

That's just a baseless assertion. Here I can do the same: implicit overloading is a great design in case of pointers and objects because a.b is always unambiguous and uniform, and -> is a harder to read and type extra operator which has no justification.

And then obviously your assertion can be used exactly the same way to similarly assert that every numeric type should have its own set of arithmetic operators, after all u4+ is also readable, easy to type, and short.

> 2)Integer promotion is not as simple because requiring explicit promotion makes a holy unreadable mess out of your code in the simplest of cases.

Integer promotion is much simpler because it's literally a never-ending source of bugs.

> This is also the reason Python has implicit promotion for its number type.

Python does not have implicit promotion for its number type, at best Python 2 had that for performance reasons (definitely not "mongo code lines with all the explicit casts" which it could not care less about), and in reality that was not even the case because it does not corrupt your data upfront as C does.

Re:C uses "&" for the address-operator because 'ampersand so... by sigsev_251 on Tuesday October 10, 2023 @11:51AM (#37833730)
Integer promotion will probably never be removed from the fundamental types (char, signed char, short, etc.). You can use `_BitInt`(N) types in the future which don't follow the implicit integer promotion rule. There are at least two compilers today that implement it (clang and SDCC).
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Wednesday October 11, 2023 @01:21AM (#37841192)
> Integer promotion will probably never be removed from the fundamental types

Oh let me assure you, I have no actual expectation that C would ever change in such a way.

Although it should be noted that both suggestions are entirely syntactic and could be gated behind a per-file (or even per function) stricture a la strict mode.

Re:C uses "&" for the address-operator because 'ampersand so... by hknapp on Tuesday October 10, 2023 @09:38AM (#37831949)
Re:C uses "&" for the address-operator because 'ampersand so... by atilaneves on Tuesday October 10, 2023 @11:15AM (#37833142)
Proof of the fact that this works is that D does exactly this.
Re:C uses "&" for the address-operator because 'ampersand so... by masklinn on Wednesday October 11, 2023 @03:25PM (#37849121)
AFAIK it works like that in most modern languages with pointers: Rust, Zig, even Go will implicitly deref pointers on attribute access.
Re:C uses "&" for the address-operator because 'ampersand so... by Snarwin on Tuesday October 10, 2023 @12:49PM (#37834489)
Interestingly, C already does this for function calls: "fptr()" is considered equivalent to "(*fptr)()".
Re:C uses "&" for the address-operator because 'ampersand so... by kps on Tuesday October 10, 2023 @01:21PM (#37834843)
A mistake, IMO; I want to be able to see right away whether a call target is static or dynamic.