Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #170585 > unrolled thread
| Started by | Spiros Bousbouras <spibou@gmail.com> |
|---|---|
| First post | 2023-06-27 09:12 +0000 |
| Last post | 2023-06-28 14:16 -0700 |
| Articles | 20 on this page of 30 — 14 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Spiros Bousbouras <spibou@gmail.com> |
|---|---|
| Date | 2023-06-27 09:12 +0000 |
| Subject | Why 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]
| From | felix@palmen-it.de (Felix Palmen) |
|---|---|
| Date | 2023-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]
| From | Spiros Bousbouras <spibou@gmail.com> |
|---|---|
| Date | 2023-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-06-27 16:06 +0100 |
| Subject | Re: 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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-06-27 18:01 +0100 |
| Subject | Re: 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]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2023-06-27 12:46 -0500 |
| Subject | Re: 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]
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2023-08-09 00:08 -0700 |
| Subject | Re: 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]
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2023-08-09 00:11 -0700 |
| Subject | Re: 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]
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2023-08-09 00:23 -0700 |
| Subject | Re: 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]
| From | Lew Pitcher <lew.pitcher@digitalfreehold.ca> |
|---|---|
| Date | 2023-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]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-06-27 17:05 +0100 |
| Subject | Re: 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]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-06-27 17:11 +0000 |
| Subject | Re: 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]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2023-06-27 10:54 -0500 |
| Subject | Re: 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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2023-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]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2023-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]
| From | Spiros Bousbouras <spibou@gmail.com> |
|---|---|
| Date | 2023-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]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2023-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