Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #170585 > unrolled thread

Why does the -> operator exist ?

Started bySpiros Bousbouras <spibou@gmail.com>
First post2023-06-27 09:12 +0000
Last post2023-06-28 14:16 -0700
Articles 20 on this page of 30 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  Why does the  ->  operator exist ? Spiros Bousbouras <spibou@gmail.com> - 2023-06-27 09:12 +0000
    Re: Why does the  ->  operator exist ? felix@palmen-it.de (Felix Palmen) - 2023-06-27 15:01 +0200
      Re: Why does the  ->  operator exist ? Spiros Bousbouras <spibou@gmail.com> - 2023-06-27 14:09 +0000
        Re: Why does the  ->  operator exist ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-06-27 15:56 +0100
    Re: Why does the -> operator exist ? Bart <bc@freeuk.com> - 2023-06-27 16:06 +0100
      Re: Why does the -> operator exist ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-06-27 18:01 +0100
        Re: Why does the -> operator exist ? BGB <cr88192@gmail.com> - 2023-06-27 12:46 -0500
      Re: Why does the -> operator exist ? fir <profesor.fir@gmail.com> - 2023-08-09 00:08 -0700
        Re: Why does the -> operator exist ? fir <profesor.fir@gmail.com> - 2023-08-09 00:11 -0700
          Re: Why does the -> operator exist ? fir <profesor.fir@gmail.com> - 2023-08-09 00:23 -0700
    Re: Why does the  ->  operator exist ? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2023-06-27 15:13 +0000
    Re: Why does the  ->  operator exist ? Kaz Kylheku <864-117-4973@kylheku.com> - 2023-06-27 15:30 +0000
      Re: Why does the -> operator exist ? Bart <bc@freeuk.com> - 2023-06-27 17:05 +0100
        Re: Why does the -> operator exist ? Kaz Kylheku <864-117-4973@kylheku.com> - 2023-06-27 17:11 +0000
    Re: Why does the -> operator exist ? BGB <cr88192@gmail.com> - 2023-06-27 10:54 -0500
    Re: Why does the  ->  operator exist ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-06-27 12:23 -0700
      Re: Why does the  ->  operator exist ? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2023-06-27 15:33 -0600
      Re: Why does the  ->  operator exist ? Spiros Bousbouras <spibou@gmail.com> - 2023-06-28 16:31 +0000
        Re: Why does the  ->  operator exist ? Kaz Kylheku <864-117-4973@kylheku.com> - 2023-06-29 03:14 +0000
      Re: Why does the  ->  operator exist ? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-07-20 18:57 -0700
        Re: Why does the  ->  operator exist ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-07-20 19:49 -0700
          Re: Why does the  ->  operator exist ? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-08-08 05:49 -0700
            Re: Why does the  ->  operator exist ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-08-08 16:33 -0700
              Re: Why does the  ->  operator exist ? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-08-14 04:34 -0700
                I love it... (Was: Why does the  ->  operator exist ?) gazelle@shell.xmission.com (Kenny McCormack) - 2023-08-14 12:41 +0000
                Re: Why does the  ->  operator exist ? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-08-14 15:10 -0700
                  Re: Why does the  ->  operator exist ? Phil Carmody <pc+usenet@asdf.org> - 2023-08-15 23:00 +0300
                  Re: Why does the  ->  operator exist ? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-08-16 05:29 -0700
        Re: Why does the  ->  operator exist ? Kaz Kylheku <864-117-4973@kylheku.com> - 2023-07-22 05:39 +0000
    Re: Why does the -> operator exist ? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2023-06-28 14:16 -0700

Page 1 of 2  [1] 2  Next page →


#170585 — Why does the -> operator exist ?

FromSpiros Bousbouras <spibou@gmail.com>
Date2023-06-27 09:12 +0000
SubjectWhy does the -> operator exist ?
Message-ID<trfLpf+N71iCzEwJm@bongo-ra.co>
I mean would it create an ambiguity if you could write  s.field
both when  s  is a structure or union and when  s  is a pointer
to a structure or union ?

[toc] | [next] | [standalone]


#170586

Fromfelix@palmen-it.de (Felix Palmen)
Date2023-06-27 15:01 +0200
Message-ID<s53rmj-dhr1.ln1@mail.home.palmen-it.de>
In reply to#170585
* Spiros Bousbouras <spibou@gmail.com>:
> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

Most likely no.

So, my answer will be an opinion: In a language like C (with explicit
resource management), pointers (taking them, dereferencing them) really
*should* be explicit. For correct code, it's important to know whether
you're dealing with a pointer or not. And the compiler gets a chance to
tell you "careful, this doesn't have the type you seemed to expect".

Yes, I know there are already a few exceptions. But looking at function
pointers, they are special anyways, as functions themselves don't exist
as types. And looking at the special evaluation of an array identifier
as a pointer to its first element, well, this really created more than
enough confusion, especially among beginners.

-- 
 Dipl.-Inform. Felix Palmen  <felix@palmen-it.de>   ,.//..........
 {web}  http://palmen-it.de  {jabber} [see email]   ,//palmen-it.de
 {pgp public key}     http://palmen-it.de/pub.txt   //   """""""""""
 {pgp fingerprint} 6936 13D5 5BBF 4837 B212  3ACC 54AD E006 9879 F231

[toc] | [prev] | [next] | [standalone]


#170587

FromSpiros Bousbouras <spibou@gmail.com>
Date2023-06-27 14:09 +0000
Message-ID<5GG1hY+aCvnXx5w2K@bongo-ra.co>
In reply to#170586
On Tue, 27 Jun 2023 15:01:16 +0200
felix@palmen-it.de (Felix Palmen) wrote:
> * Spiros Bousbouras <spibou@gmail.com>:
> > I mean would it create an ambiguity if you could write  s.field
> > both when  s  is a structure or union and when  s  is a pointer
> > to a structure or union ?
> 
> Most likely no.
> 
> So, my answer will be an opinion: In a language like C (with explicit
> resource management), pointers (taking them, dereferencing them) really
> *should* be explicit. For correct code, it's important to know whether
> you're dealing with a pointer or not. And the compiler gets a chance to
> tell you "careful, this doesn't have the type you seemed to expect".
> 
> Yes, I know there are already a few exceptions. But looking at function
> pointers, they are special anyways, as functions themselves don't exist
> as types. And looking at the special evaluation of an array identifier
> as a pointer to its first element, well, this really created more than
> enough confusion, especially among beginners.

A more similar exception is an expression  a + b  where  b  is an integer
type. a  can be a pointer or an arithmetic type.

[toc] | [prev] | [next] | [standalone]


#170588

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-06-27 15:56 +0100
Message-ID<87fs6dosx5.fsf@bsb.me.uk>
In reply to#170587
Spiros Bousbouras <spibou@gmail.com> writes:

> On Tue, 27 Jun 2023 15:01:16 +0200
> felix@palmen-it.de (Felix Palmen) wrote:
>> * Spiros Bousbouras <spibou@gmail.com>:
>> > I mean would it create an ambiguity if you could write  s.field
>> > both when  s  is a structure or union and when  s  is a pointer
>> > to a structure or union ?
>> 
>> Most likely no.
>> 
>> So, my answer will be an opinion: In a language like C (with explicit
>> resource management), pointers (taking them, dereferencing them) really
>> *should* be explicit. For correct code, it's important to know whether
>> you're dealing with a pointer or not. And the compiler gets a chance to
>> tell you "careful, this doesn't have the type you seemed to expect".
>> 
>> Yes, I know there are already a few exceptions. But looking at function
>> pointers, they are special anyways, as functions themselves don't exist
>> as types. And looking at the special evaluation of an array identifier
>> as a pointer to its first element, well, this really created more than
>> enough confusion, especially among beginners.
>
> A more similar exception is an expression  a + b  where  b  is an integer
> type. a  can be a pointer or an arithmetic type.

This could have been outlawed and replaced by &a[b].  Of course,
currently, a[b] is defined as *(a+b) so it relies on pointer arithmetic,
but a[b] could have been defined independently so as to have a+b
generate a warning.  I don't think this was ever a consideration.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#170589 — Re: Why does the -> operator exist ?

FromBart <bc@freeuk.com>
Date2023-06-27 16:06 +0100
SubjectRe: Why does the -> operator exist ?
Message-ID<u7etsq$1e0jo$1@dont-email.me>
In reply to#170585
On 27/06/2023 10:12, Spiros Bousbouras wrote:
> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

I thought you meant why C allows P->m since it does exactly the same 
thing as (*P).m.

 From your other comment, you are asking why have a dereference between 
P and m at all.

Actually this could have been made optional in this case:

       struct S* P;
       struct S  Q;

       P.m + Q.m;  // compiler transforms this to (*P).m + Q.m;

You lose some transparency, but reduce clutter and improve readability 
by not having to type (*P).m or P->m.

However you will still need it in other contexts such as:

       P;

is this evaluating the pointer, or the struct it points to? Here you 
need to choose between P and *P (-> doesn't help here: there is no member).

[toc] | [prev] | [next] | [standalone]


#170594 — Re: Why does the -> operator exist ?

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-06-27 18:01 +0100
SubjectRe: Why does the -> operator exist ?
Message-ID<874jmsq1p7.fsf@bsb.me.uk>
In reply to#170589
Bart <bc@freeuk.com> writes:

> On 27/06/2023 10:12, Spiros Bousbouras wrote:
>> I mean would it create an ambiguity if you could write  s.field
>> both when  s  is a structure or union and when  s  is a pointer
>> to a structure or union ?
>
> I thought you meant why C allows P->m since it does exactly the same thing
> as (*P).m.
>
> From your other comment, you are asking why have a dereference between P
> and m at all.
>
> Actually this could have been made optional in this case:
>
>       struct S* P;
>       struct S  Q;
>
>       P.m + Q.m;  // compiler transforms this to (*P).m + Q.m;
>
> You lose some transparency, but reduce clutter and improve readability by
> not having to type (*P).m or P->m.
>
> However you will still need it in other contexts such as:
>
>       P;
>
> is this evaluating the pointer, or the struct it points to?

The suggestion, I think, was simply to all . on a struct pointer instead
of requiring ->.

> Here you need
> to choose between P and *P (-> doesn't help here: there is no member).

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#170596 — Re: Why does the -> operator exist ?

FromBGB <cr88192@gmail.com>
Date2023-06-27 12:46 -0500
SubjectRe: Why does the -> operator exist ?
Message-ID<u7f79q$1f1pr$1@dont-email.me>
In reply to#170594
On 6/27/2023 12:01 PM, Ben Bacarisse wrote:
> Bart <bc@freeuk.com> writes:
> 
>> On 27/06/2023 10:12, Spiros Bousbouras wrote:
>>> I mean would it create an ambiguity if you could write  s.field
>>> both when  s  is a structure or union and when  s  is a pointer
>>> to a structure or union ?
>>
>> I thought you meant why C allows P->m since it does exactly the same thing
>> as (*P).m.
>>
>>  From your other comment, you are asking why have a dereference between P
>> and m at all.
>>
>> Actually this could have been made optional in this case:
>>
>>        struct S* P;
>>        struct S  Q;
>>
>>        P.m + Q.m;  // compiler transforms this to (*P).m + Q.m;
>>
>> You lose some transparency, but reduce clutter and improve readability by
>> not having to type (*P).m or P->m.
>>
>> However you will still need it in other contexts such as:
>>
>>        P;
>>
>> is this evaluating the pointer, or the struct it points to?
> 
> The suggestion, I think, was simply to all . on a struct pointer instead
> of requiring ->.
> 

Which, ironically enough, seems to works fine in practice as with the 
current type system, there are no cases in C where '.' vs '->' could be 
(functionally) ambiguous, merely cases where one is allowed but the 
other is not...


>> Here you need
>> to choose between P and *P (-> doesn't help here: there is no member).
> 

[toc] | [prev] | [next] | [standalone]


#171912 — Re: Why does the -> operator exist ?

Fromfir <profesor.fir@gmail.com>
Date2023-08-09 00:08 -0700
SubjectRe: Why does the -> operator exist ?
Message-ID<fe29aa20-4afa-4259-897b-5943cd224708n@googlegroups.com>
In reply to#170589
wtorek, 27 czerwca 2023 o 17:06:17 UTC+2 Bart napisał(a):
> On 27/06/2023 10:12, Spiros Bousbouras wrote: 
> > I mean would it create an ambiguity if you could write s.field 
> > both when s is a structure or union and when s is a pointer 
> > to a structure or union ?
> I thought you meant why C allows P->m since it does exactly the same 
> thing as (*P).m. 
> 
> From your other comment, you are asking why have a dereference between 
> P and m at all. 
> 
> Actually this could have been made optional in this case: 
> 
> struct S* P; 
> struct S Q; 
> 
> P.m + Q.m; // compiler transforms this to (*P).m + Q.m; 
> 
> You lose some transparency, but reduce clutter and improve readability 
> by not having to type (*P).m or P->m. 
> 


allowing it for fields would be incoherent with normal pointers so if so
it would bebetter to skip * for all (but not for sole fields) - i was writing on this
some years ago...there is general problem with pointers in c imo

here problem is rather this idiotic convention that* sticks to right (as far as i remeber
if i remember wrong some could correct me) in  *a.b.c.d.e becouse if you would use  *a.b.*c.d.e what does it mean ? a.b.c.d.**e ? * should stick immediate and then you coud write  s.*p or *s.p
with no problem

[toc] | [prev] | [next] | [standalone]


#171913 — Re: Why does the -> operator exist ?

Fromfir <profesor.fir@gmail.com>
Date2023-08-09 00:11 -0700
SubjectRe: Why does the -> operator exist ?
Message-ID<d58e86ab-df04-4ba4-9cdf-73020ae45e87n@googlegroups.com>
In reply to#171912
środa, 9 sierpnia 2023 o 09:08:12 UTC+2 fir napisał(a):
> wtorek, 27 czerwca 2023 o 17:06:17 UTC+2 Bart napisał(a): 
> > On 27/06/2023 10:12, Spiros Bousbouras wrote: 
> > > I mean would it create an ambiguity if you could write s.field 
> > > both when s is a structure or union and when s is a pointer 
> > > to a structure or union ? 
> > I thought you meant why C allows P->m since it does exactly the same 
> > thing as (*P).m. 
> > 
> > From your other comment, you are asking why have a dereference between 
> > P and m at all. 
> > 
> > Actually this could have been made optional in this case: 
> > 
> > struct S* P; 
> > struct S Q; 
> > 
> > P.m + Q.m; // compiler transforms this to (*P).m + Q.m; 
> > 
> > You lose some transparency, but reduce clutter and improve readability 
> > by not having to type (*P).m or P->m. 
> >
> allowing it for fields would be incoherent with normal pointers so if so 
> it would bebetter to skip * for all (but not for sole fields) - i was writing on this 
> some years ago...there is general problem with pointers in c imo 
> 
> here problem is rather this idiotic convention that* sticks to right (as far as i remeber 
> if i remember wrong some could correct me) in *a.b.c.d.e becouse if you would use *a.b.*c.d.e what does it mean ? a.b.c.d.**e ? * should stick immediate and then you coud write s.*p or *s.p 
> with no problem

i dont know who set this way (thompson, ritche or someone elese?_ but its incoherent with generally c being not idioptic becouse this *a.*b.c working as i remember is idiotic

[toc] | [prev] | [next] | [standalone]


#171914 — Re: Why does the -> operator exist ?

Fromfir <profesor.fir@gmail.com>
Date2023-08-09 00:23 -0700
SubjectRe: Why does the -> operator exist ?
Message-ID<d49458c0-49b6-46c9-ac7a-8da743484273n@googlegroups.com>
In reply to#171913
środa, 9 sierpnia 2023 o 09:12:02 UTC+2 fir napisał(a):
> środa, 9 sierpnia 2023 o 09:08:12 UTC+2 fir napisał(a): 
> > wtorek, 27 czerwca 2023 o 17:06:17 UTC+2 Bart napisał(a): 
> > > On 27/06/2023 10:12, Spiros Bousbouras wrote: 
> > > > I mean would it create an ambiguity if you could write s.field 
> > > > both when s is a structure or union and when s is a pointer 
> > > > to a structure or union ? 
> > > I thought you meant why C allows P->m since it does exactly the same 
> > > thing as (*P).m. 
> > > 
> > > From your other comment, you are asking why have a dereference between 
> > > P and m at all. 
> > > 
> > > Actually this could have been made optional in this case: 
> > > 
> > > struct S* P; 
> > > struct S Q; 
> > > 
> > > P.m + Q.m; // compiler transforms this to (*P).m + Q.m; 
> > > 
> > > You lose some transparency, but reduce clutter and improve readability 
> > > by not having to type (*P).m or P->m. 
> > > 
> > allowing it for fields would be incoherent with normal pointers so if so 
> > it would bebetter to skip * for all (but not for sole fields) - i was writing on this 
> > some years ago...there is general problem with pointers in c imo 
> > 
> > here problem is rather this idiotic convention that* sticks to right (as far as i remeber 
> > if i remember wrong some could correct me) in *a.b.c.d.e becouse if you would use *a.b.*c.d.e what does it mean ? a.b.c.d.**e ? * should stick immediate and then you coud write s.*p or *s.p 
> > with no problem
> i dont know who set this way (thompson, ritche or someone elese?_ but its incoherent with generally c being not idioptic becouse this *a.*b.c working as i remember is idiotic

as to idea of c being explicit c uspports that idea but not in full case as its seen
for example c supports the idea being transparent (no black boxes ) bit not
necessary support the idea you can see whet some things are without refering to its definitions

[toc] | [prev] | [next] | [standalone]


#170590

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2023-06-27 15:13 +0000
Message-ID<u7eua9$1dvag$1@dont-email.me>
In reply to#170585
On Tue, 27 Jun 2023 09:12:09 +0000, Spiros Bousbouras wrote:

To answer your Subject line question "Why does the -> operator exist?",
let's look at K&R "The C Programming Language" (1st edition):

  (In discusson about pointers to structures, and access to structure
   elements through such pointers, using a date structure and a pointer
   (pd) to such structure as an example)
  "If 
     p
   is a pointer to a structure, then
     p->member-of-structure
   refers to the particular member. Since
     pd
   points to the structure, the
     year
   member could also be refered to as
     (*pd).year
   but pointers to structures are so frequently used that the ->
   notation is provided as a convenient shorthand."

So, -> is syntactic sugar

> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

If
  s
is a POINTER, then
  s.field
would not just be "ambigious", it would be /wrong/. POINTERs do
not have members, STRUCTURES do. 

If, given
  struct {
    int a;
    char b;
  } a, *s = &a;
the C language permitted
  s.a = 3;
then
  s
must be considered to be the entirety of the structure. So, what
would
  if (s == &a)
test? Would it test the /addresses/ of the two structures, or
would it test the /contents/ of the two structures?


So, yes, your suggestion (as it stands) leads to ambiguity.
-- 
Lew Pitcher
"In Skills We Trust"

[toc] | [prev] | [next] | [standalone]


#170591

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-06-27 15:30 +0000
Message-ID<20230627082343.242@kylheku.com>
In reply to#170585
On 2023-06-27, Spiros Bousbouras <spibou@gmail.com> wrote:
> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

1. I suspect early C compilers didn't always maintain the type information
to be able to do that, though that isn't difficult to remedy.
You just have to know "is this declared as a pointer or not".

2. a->b was invented as a shorthand for (*a).b. Maybe that detour was
enough of a distraction not to make it immediately obvious
that another way to do that would be to have a.b have that
meaning whenever a is a pointer. That said, there is enough pointer
"decay" in C; this would just be another instance. Just like
(***f)(), (*f) and f() are equivalent (***a).b, (*a).b and a.b
could be identical.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


#170593 — Re: Why does the -> operator exist ?

FromBart <bc@freeuk.com>
Date2023-06-27 17:05 +0100
SubjectRe: Why does the -> operator exist ?
Message-ID<u7f1c8$1ef65$1@dont-email.me>
In reply to#170591
On 27/06/2023 16:30, Kaz Kylheku wrote:
 > On 2023-06-27, Spiros Bousbouras <spibou@gmail.com> wrote:
 >> I mean would it create an ambiguity if you could write  s.field
 >> both when  s  is a structure or union and when  s  is a pointer
 >> to a structure or union ?
 >
 > 1. I suspect early C compilers didn't always maintain the type 
information
 > to be able to do that, though that isn't difficult to remedy.
 > You just have to know "is this declared as a pointer or not".
 >
 > 2. a->b was invented as a shorthand for (*a).b. Maybe that detour was
 > enough of a distraction not to make it immediately obvious
 > that another way to do that would be to have a.b have that
 > meaning whenever a is a pointer. That said, there is enough pointer
 > "decay" in C; this would just be another instance. Just like
 > (***f)(), (*f) and f() are equivalent

It depends on the type of f. You can have any number of extra * than are 
necessary, but no more than one fewer.

Pointer decay in other cases is anyway due to following certain rules of 
the language. There are no such rules for pointers to structs AIUI.

(I allow such derefs to be optional in my language, but the type system 
requires them. So it works by the compiler adding in the explicit derefs 
that I omitted.

I didn't like this loss of transparency at first, but the cleaner code, 
and the way it simplifies porting to my other language which doesn't use 
pointers, makes it worth it.)

[toc] | [prev] | [next] | [standalone]


#170595 — Re: Why does the -> operator exist ?

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-06-27 17:11 +0000
SubjectRe: Why does the -> operator exist ?
Message-ID<20230627100523.643@kylheku.com>
In reply to#170593
On 2023-06-27, Bart <bc@freeuk.com> wrote:
> On 27/06/2023 16:30, Kaz Kylheku wrote:
> > On 2023-06-27, Spiros Bousbouras <spibou@gmail.com> wrote:
> >> I mean would it create an ambiguity if you could write  s.field
> >> both when  s  is a structure or union and when  s  is a pointer
> >> to a structure or union ?
> >
> > 1. I suspect early C compilers didn't always maintain the type 
> information
> > to be able to do that, though that isn't difficult to remedy.
> > You just have to know "is this declared as a pointer or not".
> >
> > 2. a->b was invented as a shorthand for (*a).b. Maybe that detour was
> > enough of a distraction not to make it immediately obvious
> > that another way to do that would be to have a.b have that
> > meaning whenever a is a pointer. That said, there is enough pointer
> > "decay" in C; this would just be another instance. Just like
> > (***f)(), (*f) and f() are equivalent
>
> It depends on the type of f. You can have any number of extra * than are 
> necessary, but no more than one fewer.

Right; f is supposed to be a function type here (or a pointer to
function). Obviously if is a pointer-to-pointer to function,
one dereference is non-negotiable.

> (I allow such derefs to be optional in my language, but the type system 
> requires them. So it works by the compiler adding in the explicit derefs 
> that I omitted.

Makes sense. So that is a form of syntactic sugar (under the school
of thought that static type is part of syntax).

> I didn't like this loss of transparency at first, but the cleaner code, 
> and the way it simplifies porting to my other language which doesn't use 
> pointers, makes it worth it.)

Also easier refactoring: like when objects switch from aggregation to
composition. Or function arguments from structures to pointers.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


#170592 — Re: Why does the -> operator exist ?

FromBGB <cr88192@gmail.com>
Date2023-06-27 10:54 -0500
SubjectRe: Why does the -> operator exist ?
Message-ID<u7f0nq$1ecr1$1@dont-email.me>
In reply to#170585
On 6/27/2023 4:12 AM, Spiros Bousbouras wrote:
> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

The distinction between "obj.field" and "obj->field" is likely almost 
entirely historical.

In my compiler (mostly used for targeting my own CPU ISA), they are 
essentially treated as equivalent, and there is no real ill effect from 
doing so.

The most one could really do here would be to separate them in the 
front-end for long enough that one can be like "Dude, you used the wrong 
operator for the type of expression." and then revert to treating them 
as equivalent from then on.

It would have mattered more for early versions of C, but as it stands 
the two original use-cases are mutually exclusive.




Is sometimes a minor annoyance when porting code back to other compilers 
which do actually care about the difference in cases where the incorrect 
operator had ended up being used for whatever reason (assuming code that 
is "relatively free" of the use of language extensions).



The most annoying at present being that of 128-big integers (__int128) 
which is only supported for certain combinations of compiler and target.


Say:
   MSVC: Generally no (except to say that it is unsupported);
   GCC: Only on certain targets;
     And, IIRC, neither GCC nor Clang supports 128-bit integer constants.
   ...

Similarly goes for the lack of de-facto standard or portable support for 
fixed and floating-point SIMD vectors and operations.

Say:
   MSVC: Well, you got "xmmintrin.h", but it sucks;
   GCC: The "__attribute__((vector_size(16)))" system;
   ...


In my compiler, it is sort of a custom system:
   Sort of part-way maps vaguely GLSL style semantics onto C;
      Native types being things like:
        __vec4f : 4x Binary32
        __vec4h : 4x Binary16
        __quatf : 4x Binary32 (Quaternion)
        __vec2f : 2x Binary32
        __vec2d : 2x Binary64
        ...
      Some storage-only special cases:
        __vec2h : 2x Binary16
          Roughly __vec4h internally just with 32-bit storage.
        __vec3f  : 3x Binary32
        ...

      The _Complex and _Imaginary types map through the same system.
        Complex types can also be cast to quaternions.
      With typical vector operators:
        + / - : Pairwise add/sub
        * / / : Pairfile multiply divide (excludes quaternions)
          For Quaternions, A*B gives a quaternion product, ...
        ^ : Dot Product
        % : Cross Product (depends on vector type)
      Pseudo fields can be used for shuffle:
        "vec.wzyx" would reverse the elements, etc.
        "vec.xz" to extract X and Z as a 2-element vector
        "vec.xxxx", ...
        "vec.x": Extract a single field.
      Can also be composed like, say, "(__vec4f){1,2,3,4}".
      ...
   Uses "__m128" and similar, but as the vector analog of "void *".
     Casting vectors:
       __m128 <-> __int128 :  Bit copy.
       __m128 <-> __vec4f/...:  Bit copy.
       __m64 <-> long long :  Bit copy.
       __m64 <-> double: Bit Copy.
     Direct cast between other types attempts to convert types by value.
       Will fail if there is a structural mismatch between the types.
       __vec4f <-> __vec4h: Fine (converts element representation).
       __vec4f <-> __vec2d: Bad (same size, but structural mismatch).

There is partial (but much less used or tested) support for matrix types 
and operators.

My compiler can also accept GCC's syntax (for cases where there is 
semantic overlap).

There is not currently any built in support for things like 
exterior/wedge/tensor operators, but are not entirely off the table (for 
the time being, these would need to be implemented as library features).


For portability, a lot of this can be wrapped in macros and similar and 
then expressed in a way appropriate to other compilers as needed (say, 
using the SSE / "xmmintrin.h" functions in MSVC, ...), but this is 
annoying and more awkward to use.

Unlike the MSVC intrinsics, there is no assumption of a direct 1:1 
mapping with underlying instructions in the ISA in my case (and some 
operators may be internally implemented using function calls; and some 
larger types, 256-bit or more, are memory-backed types, ...).

Also partly annoying being cases where Binary16 floating-point is used 
(expressed as a "short float" type), which is absent on most other 
targets. Mostly relevant for space-saving when Binary32 is overkill 
(internally in my ABI, most scalar floating-point types are expressed 
using Binary64 in registers; so the type mostly effects storage, and 
occasionally the choice of operator).


There are a lot of other extensions, but for code that needs to be able 
to be moved between compilers, the use of extension features needs to be 
kept to a minimum.

...

[toc] | [prev] | [next] | [standalone]


#170597

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-06-27 12:23 -0700
Message-ID<87fs6cso8n.fsf@nosuchdomain.example.com>
In reply to#170585
Spiros Bousbouras <spibou@gmail.com> writes:
> I mean would it create an ambiguity if you could write  s.field
> both when  s  is a structure or union and when  s  is a pointer
> to a structure or union ?

There are languages that use the `.` operator for selecting a member
from either a structure or a pointer to a structure.  Since `.name` with
a pointer prefix has no other meaning, no ambiguity is introduced.  (Ada
is an example.)

In early C (before K&R1), `prefix.member` treated the prefix as a
structure with a member named `member`, regardless of how `prefix` was
actually defined.  Member definitions were associated with struct
definitions, but were not tied to them.  Given:

    struct foo {
        int x;
        int y;
    };

the name `x` meant `an int member at an offset of 0`, and `.x` could be
applied to any lvalue.  (This is why member names for standard library
types have unique prefixes, like the tm_sec, tm_min, ... members of
struct tm.)

Thus `foo.x` where foo is a pointer would extract an int from the bytes
making up the representation of the pointer object, while `(*foo).x` or
equivalently `foo->x` would dereference foo and extract an int from the
object foo points to.

Some time between 1975 and 1978, the rules were changed so a member name
applies only to the struct (or union) type in which it's defined, but
the meaning of the `.` operator was never updated.  It *could* have
been, but it's not clear to me that it would have been worth the effort.
The `->` operator would have had to be left in place to avoid breaking
existing code, leaving us with two different ways to write the same
thing.  Also, I would argue that using `->` rather than `.` when the
prefix is a pointer makes for more explicit code, which is a good thing;
it's important to know when you're dealing with pointers.
    
-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#170598

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2023-06-27 15:33 -0600
Message-ID<1bjzvo614r.fsf@pfeifferfamily.net>
In reply to#170597
I've always preferred Pascal's syntax for this, on the basis of consistency:

foo is a pointer
foo^ is the record foo points to
foo^.bar is a field in the record

If baz is itself a record,
baz.bar is a field in the record

But of course that ship sailed nearly fifty years ago.

[toc] | [prev] | [next] | [standalone]


#170602

FromSpiros Bousbouras <spibou@gmail.com>
Date2023-06-28 16:31 +0000
Message-ID<5HB1OjHg4nJp9zZwI@bongo-ra.co>
In reply to#170597
On Tue, 27 Jun 2023 12:23:52 -0700
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
> Spiros Bousbouras <spibou@gmail.com> writes:
> > I mean would it create an ambiguity if you could write  s.field
> > both when  s  is a structure or union and when  s  is a pointer
> > to a structure or union ?
> 
> There are languages that use the `.` operator for selecting a member
> from either a structure or a pointer to a structure.  Since `.name` with
> a pointer prefix has no other meaning, no ambiguity is introduced.  (Ada
> is an example.)

Interesting. I thought one of the design principles of Ada was to be
explicit , with the idea that it helps reduce bugs.

> In early C (before K&R1), `prefix.member` treated the prefix as a
> structure with a member named `member`, regardless of how `prefix` was
> actually defined.  Member definitions were associated with struct
> definitions, but were not tied to them.  Given:
> 
>     struct foo {
>         int x;
>         int y;
>     };
> 
> the name `x` meant `an int member at an offset of 0`, and `.x` could be
> applied to any lvalue.  (This is why member names for standard library
> types have unique prefixes, like the tm_sec, tm_min, ... members of
> struct tm.)
> 
> Thus `foo.x` where foo is a pointer would extract an int from the bytes
> making up the representation of the pointer object, while `(*foo).x` or
> equivalently `foo->x` would dereference foo and extract an int from the
> object foo points to.

Even more interesting and it might even have been useful back then. Say
you have integer types T2 and T1 with T2 being double the width of T1
and you know enough about the layout of the bits in memory ; then you
can do something like

    struct two_faced_integer {
        T1 i1 ;
        T1 i2 ;
    } ;

Then if you have an object  o  of type T2 then you could do  o.i1  and
o.i2  to get 2 integers of type T1 .In an era where compilers and
processors weren't doing the optimisations they do today , this might have
been handy.

> Some time between 1975 and 1978, the rules were changed so a member name
> applies only to the struct (or union) type in which it's defined, but
> the meaning of the `.` operator was never updated.  It *could* have
> been, but it's not clear to me that it would have been worth the effort.
> The `->` operator would have had to be left in place to avoid breaking
> existing code, leaving us with two different ways to write the same
> thing.

If  ->  was already present then it wouldn't make sense to give  s.field
an idiomatic meaning when  s  is a pointer , it would just be an additional
complexity.

> Also, I would argue that using `->` rather than `.` when the
> prefix is a pointer makes for more explicit code, which is a good thing;
> it's important to know when you're dealing with pointers.

I have no strong feelings either way but I was under the impression that
Ada people do have strong feelings in favour of being explicit hence my
surprise at how Ada does things.

-- 
vlaho.ninja/prog

[toc] | [prev] | [next] | [standalone]


#170604

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-06-29 03:14 +0000
Message-ID<20230628200210.747@kylheku.com>
In reply to#170602
On 2023-06-28, Spiros Bousbouras <spibou@gmail.com> wrote:
> On Tue, 27 Jun 2023 12:23:52 -0700
> Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>> Spiros Bousbouras <spibou@gmail.com> writes:
>> > I mean would it create an ambiguity if you could write  s.field
>> > both when  s  is a structure or union and when  s  is a pointer
>> > to a structure or union ?
>> 
>> There are languages that use the `.` operator for selecting a member
>> from either a structure or a pointer to a structure.  Since `.name` with
>> a pointer prefix has no other meaning, no ambiguity is introduced.  (Ada
>> is an example.)
>
> Interesting. I thought one of the design principles of Ada was to be
> explicit , with the idea that it helps reduce bugs.

Using two tokens for two different situations is no more or less
explicit than one.

a->b does two things: dereferences the pointer and selects a member;
if we change the spelling of the operator, that doesn't change
the semantics.

To be explicit, you have to use (*a).b so that this is done using
two separate operators: *a does the dereferencing to produce
a structure, whose member is then selected.

If the same operator is used, it's a case of overloading.

But Ada is not against overloading: it supports operator overloading!

[toc] | [prev] | [next] | [standalone]


#171004

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-07-20 18:57 -0700
Message-ID<86fs5ivxfu.fsf@linuxsc.com>
In reply to#170597
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> [...] I would argue that using `->` rather than `.` when the
> prefix is a pointer makes for more explicit code, which is a good
> thing;  [...]

More explicit is not always better.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web