Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why do we have type& and type*

367 views
Skip to first unread message

Rick C. Hodgin

unread,
Apr 10, 2018, 10:27:03 AM4/10/18
to
What is the C++ reasoning for having both & and * types? Why not just
have * types?

--
Thank you! | Indianapolis, Indiana | God is love -- 1 John 4:7-9
Rick C. Hodgin | http://www.libsf.org/ | http://tinyurl.com/yaogvqhj
-------------------------------------------------------------------------
Software: LSA, LSC, Debi, RDC/CAlive, ES/1, ES/2, VJr, VFrP, Logician
Hardware: Arxoda Desktop CPU, Arxita Embedded CPU, Arlina Compute FPGA

Mr Flibble

unread,
Apr 10, 2018, 10:33:53 AM4/10/18
to
On 10/04/2018 15:26, Rick C. Hodgin wrote:
> What is the C++ reasoning for having both & and * types?  Why not just
> have * types?

Because epistemological sausages travel at the speed of light in a
vacuum. How is this possible? They have no mass and always face the
Flying Spaghetti Monster (the one true God).

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates
a world that is so full of injustice and pain. That’s what I would say."

james...@verizon.net

unread,
Apr 10, 2018, 11:39:46 AM4/10/18
to
C++ references are semantically closely related to const pointers.
Internally, code using a reference will often be implemented identically
to equivalent code using a const pointer. However, references are
syntactically more convenient than const pointers. C++ retains pointers
both for backwards compatibility with C, and because it's possible for a
pointer to be null, which is a convenient way of conveying the
information that "there is nothing to be pointed at"; there's no simple
way to use C++ references to convey the information that "there is
nothing to be referred to".
That's a matter of deliberate design, not an oversight. The C++ rules
governing references were designed to justify the assumption that a
reference always refers to an actual object of the specified type,
which makes it easier to write safe code.

Melzzzzz

unread,
Apr 10, 2018, 12:58:08 PM4/10/18
to
On 2018-04-10, Rick C. Hodgin <rick.c...@gmail.com> wrote:
> What is the C++ reasoning for having both & and * types? Why not just
> have * types?
Because of C legacy/>


--
press any key to continue or any other to quit...

Mr Flibble

unread,
Apr 10, 2018, 1:22:25 PM4/10/18
to
On 10/04/2018 15:26, Rick C. Hodgin wrote:
> What is the C++ reasoning for having both & and * types?  Why not just
> have * types?

So you can refer to an object without using pointer semantics.

Alf P. Steinbach

unread,
Apr 10, 2018, 1:45:46 PM4/10/18
to
On 10.04.2018 19:22, Mr Flibble wrote:
> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>> What is the C++ reasoning for having both & and * types?  Why not just
>> have * types?
>
> So you can refer to an object without using pointer semantics.

That's right.

Bjarne added references to support user-defined operators. Without
references they would be really ugly and not like built-in operators.

I think that tidbit came from his "evolution" book, which I don't have,
sorry. Googling will probably find references. Maybe.


Cheers!,

- Alf


Tim Rentsch

unread,
Apr 12, 2018, 7:02:17 AM4/12/18
to
james...@verizon.net writes:

> C++ references are semantically closely related to const pointers.
> [...] However, references are syntactically more convenient than
> const pointers. C++ retains pointers both for backwards
> compatibility with C, and because its possible for a pointer to be
> null, [...]

And because pointers are mutable.

Richard

unread,
Apr 12, 2018, 2:13:46 PM4/12/18
to
[Please do not mail me a copy of your followup]

Tim Rentsch <t...@alumni.caltech.edu> spake the secret code
<kfnin8w...@x-alumni2.alumni.caltech.edu> thusly:
...and nullptr'able.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Manfred

unread,
Apr 12, 2018, 2:14:31 PM4/12/18
to
On 4/10/2018 7:45 PM, Alf P. Steinbach wrote:
> On 10.04.2018 19:22, Mr Flibble wrote:
>> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>>> What is the C++ reasoning for having both & and * types?  Why not just
>>> have * types?
>>
>> So you can refer to an object without using pointer semantics.
>
> That's right.
>
> Bjarne added references to support user-defined operators. Without
> references they would be really ugly and not like built-in operators.

In fact it achieved a somewhat broader goal:
At the time C++ was invented, some languages (notably C) used
call-by-value argument evaluation, other (e.g. FORTRAN) used
call-by-reference evaluation.
Both methods had, and have, their pros and cons. So that when Bjarne
added the possibility to do both in his language, he achieved some
feature-completeness with argument evaluation.
Now, since it is possible to use pointers in C to achieve
pass-by-reference functionality, from this point of view the difference
is more semantical than substantial, as Mr. Flibble noted.

Obviously this resulted in some useful peculiar properties of
references: notably, they are immutable, and they are guaranteed to
refer to an actual object (if you don't break he rules).
It also resulted in some unconventional peculiarities, stemming from the
fact that "a reference is not an object", as Bjarne says, so that their
own semantics is substantially different from that of any actual C++
object (including pointers).
I think this last bit is what may make them less attractive to some.

Jorgen Grahn

unread,
Apr 12, 2018, 2:53:01 PM4/12/18
to
Page 85: "References were introduced primarily to support operator
overloading." Then he goes on to mention Algol68 as an inspiration.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

bartc

unread,
Apr 12, 2018, 2:54:34 PM4/12/18
to
On 12/04/2018 19:14, Manfred wrote:
> On 4/10/2018 7:45 PM, Alf P. Steinbach wrote:
>> On 10.04.2018 19:22, Mr Flibble wrote:
>>> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>>>> What is the C++ reasoning for having both & and * types?  Why not just
>>>> have * types?
>>>
>>> So you can refer to an object without using pointer semantics.
>>
>> That's right.
>>
>> Bjarne added references to support user-defined operators. Without
>> references they would be really ugly and not like built-in operators.
>
> In fact it achieved a somewhat broader goal:
> At the time C++ was invented, some languages (notably C) used
> call-by-value argument evaluation, other (e.g. FORTRAN) used
> call-by-reference evaluation.
> Both methods had, and have, their pros and cons. So that when Bjarne
> added the possibility to do both in his language, he achieved some
> feature-completeness with argument evaluation.
> Now, since it is possible to use pointers in C to achieve
> pass-by-reference functionality, from this point of view the difference
> is more semantical than substantial, as Mr. Flibble noted.
>

I use what I call pass-by-reference, indicated by a '&', in one of my
own languages, and I'd be interested to know if it's anything like what
is being talked about here.

I'll give examples in C syntax as people are familiar with that. First
example:

void getdims(int width, int height) {width=10; height;}
int h=0, w=0;
getdims(h,w);

This function is not useful as written because it doesn't return
anything to the caller. It has to be written like this:

void getdims(int *width, int *height) {*width=10; *height;}
int h=0, w=0;
getdims(&h,&w);

Now it works, but it needs explicit address-of and dereference operators
in both caller and function. Both versions use pass-by-value.

My & feature would work like this:

void getdims(int &width, int &height) {width=10; height;}
int h=0, w=0;
getdims(h,w);

& is implicitly added to arguments, and * to any use of a & parameter
within the function body. getdims(0,0) would not work (&0 is illegal),
so null pointers are not possible, but code doesn't even know it's using
pointers.

So, is this anything like C++'s & parameters?

--
bartc

David Brown

unread,
Apr 12, 2018, 3:29:03 PM4/12/18
to
I am guessing you meant something like "{width = 10; height = 20;}" ?

>   int h=0, w=0;
>   getdims(h,w);
>
> & is implicitly added to arguments, and * to any use of a & parameter
> within the function body. getdims(0,0) would not work (&0 is illegal),
> so null pointers are not possible, but code doesn't even know it's using
> pointers.
>
> So, is this anything like C++'s & parameters?
>

Yes, that is /exactly/ like C++ reference parameters.

Manfred

unread,
Apr 12, 2018, 3:29:40 PM4/12/18
to
On 4/12/2018 8:54 PM, bartc wrote:
> On 12/04/2018 19:14, Manfred wrote:
>> On 4/10/2018 7:45 PM, Alf P. Steinbach wrote:
>>> On 10.04.2018 19:22, Mr Flibble wrote:
>>>> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>>>>> What is the C++ reasoning for having both & and * types?  Why not just
>>>>> have * types?
>>>>
>>>> So you can refer to an object without using pointer semantics.
>>>
>>> That's right.
>>>
>>> Bjarne added references to support user-defined operators. Without
>>> references they would be really ugly and not like built-in operators.
>>
>> In fact it achieved a somewhat broader goal:
>> At the time C++ was invented, some languages (notably C) used
>> call-by-value argument evaluation, other (e.g. FORTRAN) used
>> call-by-reference evaluation.
>> Both methods had, and have, their pros and cons. So that when Bjarne
>> added the possibility to do both in his language, he achieved some
>> feature-completeness with argument evaluation.
>> Now, since it is possible to use pointers in C to achieve
>> pass-by-reference functionality, from this point of view the
>> difference is more semantical than substantial, as Mr. Flibble noted.
>>
>
> I use what I call pass-by-reference, indicated by a '&', in one of my
> own languages, and I'd be interested to know if it's anything like what
> is being talked about here.
>


> My & feature would work like this:
>
>   void getdims(int &width, int &height) {width=10; height;}
>   int h=0, w=0;
>   getdims(h,w);

This looks exactly like what C++ does (although you probably inverted h,
w in the getdims call)

>
> & is implicitly added to arguments, and * to any use of a & parameter
> within the function body. getdims(0,0) would not work (&0 is illegal),
The implementation is different, but the semantics hold.
In C++ the following would be illegal:

void foo(int& x);
foo(0);

because 0 is not an lvalue, so it is not possible to take a reference on it.
But the following would be legal:

void foo(const int& x);
foo(0);

Which is just one example of how many devils get hidden in the details
of a tiny little &

> so null pointers are not possible, but code doesn't even know it's using
> pointers.
>
> So, is this anything like C++'s & parameters?
>
Basically yes.

bartc

unread,
Apr 12, 2018, 4:13:50 PM4/12/18
to
On 12/04/2018 20:28, David Brown wrote:
> On 12/04/18 20:54, bartc wrote:

>> My & feature would work like this:
>>
>>    void getdims(int &width, int &height) {width=10; height;}
>
> I am guessing you meant something like "{width = 10; height = 20;}" ?

Yes; I wondered what happened to all my height=20's. I'm sure they were
there before I posted! (And how did you know it was 20?)

>
>>    int h=0, w=0;
>>    getdims(h,w);
>>
>> & is implicitly added to arguments, and * to any use of a & parameter
>> within the function body. getdims(0,0) would not work (&0 is illegal),
>> so null pointers are not possible, but code doesn't even know it's
>> using pointers.
>>
>> So, is this anything like C++'s & parameters?
>>
>
> Yes, that is /exactly/ like C++ reference parameters.

OK. In this case it seems a remarkably simple feature to implement
(perhaps 20 or 30 extra lines in a compiler). Something C could do with
perhaps.

(And to answer the OP's question, & can be applied to any parameter
type, including one that happens to have * for a pointer. An extra
pointer level will be added behind the scenes, but you write code on the
basis of that visible * pointer.

Without &, you'd have to write functions like the middle of my examples.
Which also makes it easier to pass null or invalid pointers.)

--
bartc

Paavo Helde

unread,
Apr 12, 2018, 4:17:08 PM4/12/18
to
On 12.04.2018 21:54, bartc wrote:

>
> I use what I call pass-by-reference, indicated by a '&', in one of my
> own languages, and I'd be interested to know if it's anything like what
> is being talked about here.
>
> I'll give examples in C syntax as people are familiar with that. First
> example:
>
> void getdims(int width, int height) {width=10; height;}
> int h=0, w=0;
> getdims(h,w);
>
> This function is not useful as written because it doesn't return
> anything to the caller. It has to be written like this:
>
> void getdims(int *width, int *height) {*width=10; *height;}

*height; is a NOP.

> int h=0, w=0;
> getdims(&h,&w);

Arguments in the wrong order. This actually suggests encapsulating these
numbers into a Dims struct where such mixups would be less probable.

>
> Now it works, but it needs explicit address-of and dereference operators
> in both caller and function. Both versions use pass-by-value.
>
> My & feature would work like this:
>
> void getdims(int &width, int &height) {width=10; height;}
> int h=0, w=0;
> getdims(h,w);
>
> & is implicitly added to arguments, and * to any use of a & parameter
> within the function body. getdims(0,0) would not work (&0 is illegal),
> so null pointers are not possible, but code doesn't even know it's using
> pointers.

Yes, this is exactly as references work in C++.

&0 would not be a null pointer, but a pointer to some zero constant
somewhere (hopefully not in the global table of constants ;-). Null
references are not possible because for that one should pass an object
which resides at address zero, but it is not possible to create such an
object, and trying to fake it by dereferencing a null pointer is illegal
anyway.

That said, using references for such hidden output is usually not a good
idea from the readability point. In C++ one could use something like
that instead (assuming we do not want to create a Dims struct or something)

std::pair<int,int> getdims() {
return std::make_pair(10, 10);
}

int h=0, w=0;
std::tie(w, h) = getdims();






Rick C. Hodgin

unread,
Apr 12, 2018, 4:27:49 PM4/12/18
to
On Tuesday, April 10, 2018 at 11:39:46 AM UTC-4, james...@verizon.net wrote:
> On Tuesday, April 10, 2018 at 10:27:03 AM UTC-4, Rick C. Hodgin wrote:
> > What is the C++ reasoning for having both & and * types? Why not just
> > have * types?
>
> C++ references are semantically closely related to const pointers.
> Internally, code using a reference will often be implemented identically
> to equivalent code using a const pointer. However, references are
> syntactically more convenient than const pointers. C++ retains pointers
> both for backwards compatibility with C, and because it's possible for a
> pointer to be null, which is a convenient way of conveying the
> information that "there is nothing to be pointed at"; there's no simple
> way to use C++ references to convey the information that "there is
> nothing to be referred to".
> That's a matter of deliberate design, not an oversight. The C++ rules
> governing references were designed to justify the assumption that a
> reference always refers to an actual object of the specified type,
> which makes it easier to write safe code.

Wouldn't it be more desirable to keep them as pointers and use a
keyword to indicate it can't be NULL? We already use things like
const. Couldn't we use nonull?

void CAbc::func(const nonull CXyz* p)
{
// We know p will be non-NULL, so it can be used
}

And wouldn't it be possible to auto-create reference instances of
the pointer content, so something like p& is available for use with
that syntax?

// Some sample code
p->member // Accesses as pointer
p&.member // Accesses as reference

I don't see a reason to have both with the nonull keyword, and the
ability to reference pointer content as a reference. And if we're
going to go that far, why not just make it so that if we have the
token name in scope, and we reference it using the . syntax, then
it automatically handles the translation for us:

p->member // Accesses as pointer
p.member // Accesses as reference

It would remove some of the hidden compiler injection code for
passed parameters, but I actually think that's desirable, because
it's unclear from this:

int i = 5;
otherfunc(i);

If i is passed by reference or value. If you removed the ability
to pass by reference, it would be required to be clear in source
code:

int i = 5;
otherfunc(&i);

There would be no ambiguity. The only thing you'd have to have
then is knowledge of otherfunc() and if it included the nonull
keyword or not, but that's really only important to otherfunc()
and the compiler validating parameters at compile-time.

--
Rick C. Hodgin

Ian Collins

unread,
Apr 12, 2018, 4:32:20 PM4/12/18
to
On 04/13/2018 08:27 AM, Rick C. Hodgin wrote:
> On Tuesday, April 10, 2018 at 11:39:46 AM UTC-4, james...@verizon.net wrote:
>> On Tuesday, April 10, 2018 at 10:27:03 AM UTC-4, Rick C. Hodgin wrote:
>>> What is the C++ reasoning for having both & and * types? Why not just
>>> have * types?
>>
>> C++ references are semantically closely related to const pointers.
>> Internally, code using a reference will often be implemented identically
>> to equivalent code using a const pointer. However, references are
>> syntactically more convenient than const pointers. C++ retains pointers
>> both for backwards compatibility with C, and because it's possible for a
>> pointer to be null, which is a convenient way of conveying the
>> information that "there is nothing to be pointed at"; there's no simple
>> way to use C++ references to convey the information that "there is
>> nothing to be referred to".
>> That's a matter of deliberate design, not an oversight. The C++ rules
>> governing references were designed to justify the assumption that a
>> reference always refers to an actual object of the specified type,
>> which makes it easier to write safe code.
>
> Wouldn't it be more desirable to keep them as pointers and use a
> keyword to indicate it can't be NULL? We already use things like
> const. Couldn't we use nonull?

No, just more clutter and more importantly, it wouldn't help with used
defined operators.

--
Ian

james...@verizon.net

unread,
Apr 12, 2018, 5:00:38 PM4/12/18
to
On Thursday, April 12, 2018 at 4:27:49 PM UTC-4, Rick C. Hodgin wrote:
> On Tuesday, April 10, 2018 at 11:39:46 AM UTC-4, james...@verizon.net wrote:
> > On Tuesday, April 10, 2018 at 10:27:03 AM UTC-4, Rick C. Hodgin wrote:
> > > What is the C++ reasoning for having both & and * types? Why not just
> > > have * types?
> >
> > C++ references are semantically closely related to const pointers.
> > Internally, code using a reference will often be implemented identically
> > to equivalent code using a const pointer. However, references are
> > syntactically more convenient than const pointers. C++ retains pointers
> > both for backwards compatibility with C, and because it's possible for a
> > pointer to be null, which is a convenient way of conveying the
> > information that "there is nothing to be pointed at"; there's no simple
> > way to use C++ references to convey the information that "there is
> > nothing to be referred to".
> > That's a matter of deliberate design, not an oversight. The C++ rules
> > governing references were designed to justify the assumption that a
> > reference always refers to an actual object of the specified type,
> > which makes it easier to write safe code.
>
> Wouldn't it be more desirable to keep them as pointers and use a
> keyword to indicate it can't be NULL?

No, because doing so would discard the main motivating feature for references: the simpler syntax for using them.

Rick C. Hodgin

unread,
Apr 12, 2018, 5:15:41 PM4/12/18
to
Did you read the rest of my post? When passing pointers like that,
auto-allow the reference syntax when a name is used in a reference
syntax that goes back to a pointer.

nonull CAbc* abc;
abc->member(); // As pointer
abc.member(); // As reference

nonull int* i;
*i = 5; // As pointer
i = 5; // As reference

Why even deal with the various syntaxes in the large code blocks?
Define them once at some place (in the class, as a parameter, or
a global or local, etc.), and then use them how you see fit.

So long as there isn't a name collision ... why not?

--
Rick C. Hodgin

Mr Flibble

unread,
Apr 12, 2018, 5:20:25 PM4/12/18
to
On 12/04/2018 22:15, Rick C. Hodgin wrote:

>
>     nonull int* i;
>     *i = 5;           // As pointer
>     i = 5;            // As reference

And if you want to make the pointer address 5 rather than what it points
to 5?

Try thinking before posting.

bartc

unread,
Apr 12, 2018, 5:52:22 PM4/12/18
to
On 12/04/2018 21:16, Paavo Helde wrote:
> On 12.04.2018 21:54, bartc wrote:

>> I'll give examples in C syntax as people are familiar with that. First
>> example:
>>
>>    void getdims(int width, int height) {width=10; height;}
>>    int h=0, w=0;
>>    getdims(h,w);

> Arguments in the wrong order.

Yeah, I didn't test the C fragments before posting.

> &0 would not be a null pointer, but a pointer to some zero constant
> somewhere (hopefully not in the global table of constants ;-).

Really? In my language, I guess in C too, & must be applied to an
lvalue. A constant number isn't an lvalue, otherwise you could do 0=1.

The reason for the reference would normally be to be able to modify or
replace the caller's data. What would be the purpose of changing that 0?
Its new value can't be accessed.

Null
> references are not possible because for that one should pass an object
> which resides at address zero, but it is not possible to create such an
> object, and trying to fake it by dereferencing a null pointer is illegal
> anyway.
>
> That said, using references for such hidden output is usually not a good
> idea from the readability point. In C++ one could use something like
> that instead (assuming we do not want to create a Dims struct or something)
>
> std::pair<int,int> getdims() {
>     return std::make_pair(10, 10);
> }
>
> int h=0, w=0;
> std::tie(w, h) = getdims();

This sort of thing I used for incidental return values in addition to
the main return value. Or where you want to modify multiple data in the
caller. You don't always want the bother of creating a special return
type and it's not always appropriate.

This is an actual example from C:

char* loadjpeg(char* filename, int* width, *height);

The main return value is a pointer to image data, or NULL on error. But
when it works, dimensions are returned via those two values.

This is where references would be a tidier way of doing things.

(In C also, a parameter like int* could equally be used to pass arrays
[because the language is messed up like that], so using int& would tell
you this is a reference to a single int object, and you can only treat
it as an int within the function.)

--
bartc

>
>
>
>
>
>

David Brown

unread,
Apr 12, 2018, 6:06:03 PM4/12/18
to
On 12/04/18 22:13, bartc wrote:
> On 12/04/2018 20:28, David Brown wrote:
>> On 12/04/18 20:54, bartc wrote:
>
>>> My & feature would work like this:
>>>
>>>    void getdims(int &width, int &height) {width=10; height;}
>>
>> I am guessing you meant something like "{width = 10; height = 20;}" ?
>
> Yes; I wondered what happened to all my height=20's. I'm sure they were
> there before I posted! (And how did you know it was 20?)
>

We have battled for so long that I can read your mind :-)

>>
>>>    int h=0, w=0;
>>>    getdims(h,w);
>>>
>>> & is implicitly added to arguments, and * to any use of a & parameter
>>> within the function body. getdims(0,0) would not work (&0 is
>>> illegal), so null pointers are not possible, but code doesn't even
>>> know it's using pointers.
>>>
>>> So, is this anything like C++'s & parameters?
>>>
>>
>> Yes, that is /exactly/ like C++ reference parameters.
>
> OK. In this case it seems a remarkably simple feature to implement
> (perhaps 20 or 30 extra lines in a compiler). Something C could do with
> perhaps.
>

I hope you are sitting down, because I agree with you! I think
references could be a convenient feature in C programming, and would be
easy to implement - they are basically just syntactic sugar for constant
pointers with a non-null restriction.

There is one issue, however, that might put people off. When you call
"getdims(h, w);" in C, you know that "h" and "w" will not be changed.
That is gone if you have reference parameters. The C++ world seems to
have accepted this without trouble, but the C world might be more
conservative.

David Brown

unread,
Apr 12, 2018, 6:16:53 PM4/12/18
to
On 12/04/18 22:16, Paavo Helde wrote:
> On 12.04.2018 21:54, bartc wrote:
>
>>
>> I use what I call pass-by-reference, indicated by a '&', in one of my
>> own languages, and I'd be interested to know if it's anything like what
>> is being talked about here.
>>
>> I'll give examples in C syntax as people are familiar with that. First
>> example:
>>
>>    void getdims(int width, int height) {width=10; height;}
>>    int h=0, w=0;
>>    getdims(h,w);
>>
>> This function is not useful as written because it doesn't return
>> anything to the caller. It has to be written like this:
>>
>>    void getdims(int *width, int *height) {*width=10; *height;}
>
> *height; is a NOP.
>
>>    int h=0, w=0;
>>    getdims(&h,&w);
>
> Arguments in the wrong order. This actually suggests encapsulating these
> numbers into a Dims struct where such mixups would be less probable.

I really wish C and C++ would get support for named parameters - that
would stop this sort of mistake being possible.

>
>>
>> Now it works, but it needs explicit address-of and dereference operators
>> in both caller and function. Both versions use pass-by-value.
>>
>> My & feature would work like this:
>>
>>    void getdims(int &width, int &height) {width=10; height;}
>>    int h=0, w=0;
>>    getdims(h,w);
>>
>> & is implicitly added to arguments, and * to any use of a & parameter
>> within the function body. getdims(0,0) would not work (&0 is illegal),
>> so null pointers are not possible, but code doesn't even know it's using
>> pointers.
>
> Yes, this is exactly as references work in C++.
>
> &0 would not be a null pointer, but a pointer to some zero constant
> somewhere (hopefully not in the global table of constants ;-). Null
> references are not possible because for that one should pass an object
> which resides at address zero, but it is not possible to create such an
> object, and trying to fake it by dereferencing a null pointer is illegal
> anyway.
>
> That said, using references for such hidden output is usually not a good
> idea from the readability point. In C++ one could use something like
> that instead (assuming we do not want to create a Dims struct or something)
>
> std::pair<int,int> getdims() {
>     return std::make_pair(10, 10);
> }
>
> int h=0, w=0;
> std::tie(w, h) = getdims();
>

Or:

auto [w, h] = getdims();

But that still has the problem of being able to mix up the height and
width. I dislike returning pairs unless the elements are interchangeable.

auto getdims() {
return (struct { int width; int height; }) { 10, 20 };
}

auto dims = getdims();
auto area = dims.height * dims.width;




Ian Collins

unread,
Apr 12, 2018, 6:22:06 PM4/12/18
to
On 04/13/2018 10:05 AM, David Brown wrote:
> On 12/04/18 22:13, bartc wrote:
>>
>> OK. In this case it seems a remarkably simple feature to implement
>> (perhaps 20 or 30 extra lines in a compiler). Something C could do with
>> perhaps.
>>
>
> I hope you are sitting down, because I agree with you! I think
> references could be a convenient feature in C programming, and would be
> easy to implement - they are basically just syntactic sugar for constant
> pointers with a non-null restriction.

It would also help put an end to the eternal can't tell the size of an
array function parameter debate :)

--
Ian.

Rick C. Hodgin

unread,
Apr 12, 2018, 7:40:52 PM4/12/18
to
On Thursday, April 12, 2018 at 5:20:25 PM UTC-4, Mr Flibble wrote:
> On 12/04/2018 22:15, Rick C. Hodgin wrote:
>
> >
> >     nonull int* i;
> >     *i = 5;           // As pointer
> >     i = 5;            // As reference
>
> And if you want to make the pointer address 5 rather than what it points
> to 5?

Nope. To assign a pointer from a constan t would require a cast.
To workaround it, use the syntax i& for reference usage. It would
signal it's a reference visually, and remove ambiguity.

> Try thinking before posting.

Mitch: "Did you know there's a guy living in our closet?"
Chris: "You've seen him too?"
Mitch: "Who is he?"
Chris: "Hollyfeld."
Mitch: "Why does he keep going into our closet?"
Chris: "Why do you keep going into our closet?"
Mitch: "To get my clothes. But that's not why he keeps going in there."
Chris: "Of course not, Mitch. He's twice your size. Your clothes
would never fit him. "
Mitch: "Yeah."
Chris: "Think before you ask these things, Mitch. Twenty points
higher than me, thinks a big guy like that can wear his
clothes?"

--
Rick C. Hodgin

bartc

unread,
Apr 12, 2018, 8:17:03 PM4/12/18
to
On 12/04/2018 22:15, Rick C. Hodgin wrote:

>     nonull CAbc* abc;
>     abc->member();    // As pointer
>     abc.member();     // As reference
>
>     nonull int* i;
>     *i = 5;           // As pointer
>     i = 5;            // As reference

So both *i and i involve a dereference, and both have type 'int'?

That means you can write: *i = i; or i=*i; ?

And, if you want to assign to the pointer itself as Mr Flibble said,
what goes on the left; is it still:

i = <a pointer> ?

So the type of 'i' here depends on the whether the RHS is an int or
pointer? (You may just have re-invented Algol68.)

(You seem to have a penchant for inventing obscure, ambiguous, and
confusing language features of little or no discernible benefit that
anyone else can see. I wonder if that tells you something...)

> nonull CAbc* abc;
> abc->member(); // As pointer
> abc.member(); // As reference
>

OK, let's go with this, and extend it to:

nonull CAbc** def;

(**def).member();
(*def).member();
(*def)->member();
def->member();

Are these all valid? I assume the pattern is, if there are N pointer
levels, you can deref N times, or N-1 times. One slight problem, these
two expressions have the same rank, but abc and def have different types:

abc->member();
def->member();

More confusion.

The idea of a & reference parameter, is that apart from that, you don't
need to bother with pointers at all. Or with & on arguments; it's not
clear how your scheme deals with that, unless it is to either use & or not.

(And also, as I think of my implementation of &, the mechanism for
dealing with references exists outside of the type system of the language.

So that in:

void fn(int &a, int* &b){a, b;}

the parameter a always has type int; b always has type int*. Calling
fn(x,y), x must be of type int, and y must be of type int*. Very
straightforward. And the exactly the same as if the function was:

void fn(int a, int* b){a, b;}
)


--
bartc

Paavo Helde

unread,
Apr 13, 2018, 12:34:51 AM4/13/18
to
On 13.04.2018 0:52, bartc wrote:
> On 12/04/2018 21:16, Paavo Helde wrote:
>> &0 would not be a null pointer, but a pointer to some zero constant
>> somewhere (hopefully not in the global table of constants ;-).
>
> Really? In my language, I guess in C too, & must be applied to an
> lvalue. A constant number isn't an lvalue, otherwise you could do 0=1.

Yes, that's one of the reasons why in C or C++ a thing like &0 is not
valid. But I think there were some languages where you could indeed do
0=1. For example Fortran, with the “literal pool” optimization. See e.g.
the quiz at
"https://stuff.mit.edu/afs/net/user/tytso/archive/hackers.test" :

0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?


David Brown

unread,
Apr 13, 2018, 3:43:21 AM4/13/18
to
You can do it in Forth too. But there you are not changing the value of
the constant 0, you are redefining the meaning of "0":

0 1 + .

Puts 0 on the data stack, puts 1 on the stack, adds them, and prints the
result of 1.

: 0 1 ;

Defines "0" to be a word (a Forth function/macro equivalent) that pushes
the value 1 onto the data stack.

0 1 + .

Calls the word "0" pushing 1 on the data stack, then puts another 1 on
the stack, adds them, and prints the result of 2.


People who think C has too much scope for error and confusion should try
a few other languages!




Stuart Redmann

unread,
Apr 13, 2018, 9:31:42 AM4/13/18
to
bartc <b...@freeuk.com> wrote:
> On 12/04/2018 20:28, David Brown wrote:
>>
>> I am guessing you meant something like "{width = 10; height = 20;}" ?
>
> Yes; I wondered what happened to all my height=20's. I'm sure they were
> there before I posted! (And how did you know it was 20?)

David certainly knows that "= 20" might be misinterpreted by some news
server as url-encoded space, probably because there are some news clients
out there that transmit the contents of postings using url encoding.

Regards,
Stuart

Tim Rentsch

unread,
Apr 13, 2018, 10:12:45 AM4/13/18
to
Manfred <non...@invalid.add> writes:

> On 4/10/2018 7:45 PM, Alf P. Steinbach wrote:
>
>> On 10.04.2018 19:22, Mr Flibble wrote:
>>
>>> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>>>
>>>> What is the C++ reasoning for having both & and * types? Why not just
>>>> have * types?
>>>
>>> So you can refer to an object without using pointer semantics.
>>
>> That's right.
>>
>> Bjarne added references to support user-defined operators. Without
>> references they would be really ugly and not like built-in
>> operators.
>
> In fact it achieved a somewhat broader goal:
> At the time C++ was invented, some languages (notably C) used
> call-by-value argument evaluation, other (e.g. FORTRAN) used
> call-by-reference evaluation.

I'm pretty sure FORTRAN used call by value-result, at least
in the FORTRAN IV era which is when I learned FORTRAN.

Tim Rentsch

unread,
Apr 13, 2018, 10:13:34 AM4/13/18
to
legaliz...@mail.xmission.com (Richard) writes:

> Tim Rentsch <t...@alumni.caltech.edu> spake the secret code
> <kfnin8w...@x-alumni2.alumni.caltech.edu> thusly:
>
>> james...@verizon.net writes:
>>
>>> C++ references are semantically closely related to const pointers.
>>> [...] However, references are syntactically more convenient than
>>> const pointers. C++ retains pointers both for backwards
>>> compatibility with C, and because its possible for a pointer to be
>>> null, [...]
>>
>> And because pointers are mutable.
>
> ...and nullptr'able.

Wasn't that already pointed out by James Kuyper's comment?

David Brown

unread,
Apr 13, 2018, 10:27:27 AM4/13/18
to
I do know that, and I considered it - but I thought it more likely that
he just forgot, especially since it has not been replaced by a space
character.

But it's another reason to use spaces properly - "height = 20" would not
be misinterpreted!


james...@verizon.net

unread,
Apr 13, 2018, 10:34:42 AM4/13/18
to
No, I ignored that part of your suggestion - allowing pointers to be
confused with non-pointers is not any sane person's idea of a
improvement to C. Sorry - I should have mentioned that.

Rick C. Hodgin

unread,
Apr 13, 2018, 10:56:35 AM4/13/18
to
I had the thought referencing items with the trailing & would be
desirable to use pointers as reference, such as i& = 5;.

And in the case where there is no ambiguity, it could be used
without it, such as i = 5;.

It's not solidified yet, and I'm still contemplating it. I just
think there may be room for simplification here. The need to have
a reference and a pointer exist, but if there's a way to better
coordinate it that's what I'm after.

--
Rick C. Hodgin

Manfred

unread,
Apr 13, 2018, 1:30:32 PM4/13/18
to
My time with FORTRAN dates back a very long time ago (fortran 77 was the
one I learned), so I'm a bit rusty, but I'm positive I was taught it was
call by reference.
Both 'by reference' and 'by value-result' are very similar - in fact
they are designed to produce the same result in common circumstances.
Out of pure nostalgia I tried a simple shot at g77 and f95, which shows
that a call foo(3.0) would be allowed as long as the argument is not
modified, but it would crash at the first attempt to modify it.

This would suggest it behaves like call by reference - i.e. no copy is
made of the argument.
I still have a f77 manual somewhere, but honestly I have not opened it
for a long time.

Rosario19

unread,
Apr 14, 2018, 6:01:27 AM4/14/18
to
On Tue, 10 Apr 2018 10:26:50 -0400, "Rick C. Hodgin" wrote:

>What is the C++ reasoning for having both & and * types? Why not just
>have * types?

I agree 100% in what compiler of C++ allow to me to write in this
argument

I impose, one other law on this argument... example

type v;

f(&v) // with f(type*v) this can use and change v and use pointer as
arg
...
g(v) // with g(type&v) this not change v, but use v only (for my
personal choose to do that as law in programming) the arg v is a
hidden pointer

h(v) // with h(type v); this can not change v, but pass all data of v
in the stack or in some other place, and not just a pointer
(so has to need the constructor is called in the moment one call h()
the distructor at the end of h() is called etc)


Rosario19

unread,
Apr 14, 2018, 6:07:03 AM4/14/18
to
On Sat, 14 Apr 2018 12:01:16 +0200, Rosario19 wrote:

>g(v) // with g(type&v) this not change v, but use v only (for my
>personal choose to do that as law in programming) the arg v is a
>hidden pointer
>
>h(v) // with h(type v); this can not change v, but pass all data of v
>in the stack or in some other place, and not just a pointer
>(so has to need the constructor is called in the moment one call h()
>the distructor at the end of h() is called etc)

in few word here in h function more than g()

there is one constructor operator for doing the copy of v tmp, one =
operator for doing tmp=v, one destructor operator for eliminate tmp
when h end

Bonita Montero

unread,
Apr 16, 2018, 12:57:48 PM4/16/18
to
References are most convenient with overloaded operators.
Imagine what would happen if whe have only pointers and we would
add two strings through the global concatenation-operator. You
would have to concatenate the stings with "&strA + &strB".

james...@verizon.net

unread,
Apr 16, 2018, 3:18:14 PM4/16/18
to
In C++ as it's currently defined, when an operator overload is
applicable, the expression "a op b" is basically defined as calling
operator op(a, b), and similarly for unary functions. (When the operator
overload is a member function, 'a' is implicitly *this rather than
explicitly appearing in the function declaration, but it's the same
basic idea).
In a language derived from C90, that poses a problem, because several
expression types are defined as having a result which an lvalue (
(lvalue), *pointer_to_object, pointer_to_object[int], lvalue.member,
lvalue->member), but a function-call expression isn't one of them. C++
dealt with this problem by allowing such functions to be given a return
type which is a reference. Also, several expressions have, as their
defined behavior, modification of the value stored in one of the
operands (++, --, =, and compound assignment), which is inconsistent
with C's pass-by value semantics for function arguments. C++ dealt with
this problem by allowing function arguments to be references.

However, it would have been perfectly feasible to specify that when an
operator overload applies to one of those operators, the interpretation
would be different. for instance, a[b] could have been defined as
equivalent to *operator[](a,b), and ++a could have been define as
equivalent to operator++(&a).
Three of those operators already have special-case handling that doesn't
fit the general pattern I described above: "An expression x->m is
interpreted as (x.operator->())->m ..." (16.5.6p1) and "If the function
is a non-static member function with one parameter (which shall be of
type int) or a non-member function with two parameters (the second of
which shall be of type int), it defines the postfix increment operator
++ for objects of that type." (16.5.7p1), and similarly for --
(16.5.7p2).

It would have been no great additional difficulty providing special
handling for unary*, [], ++, --, and the assignment operators, too.
References weren't added to C++ because they were needed to implement
operator overloads. There are C compilers that provide operator
overloading as an extension, using precisely this approach.
References were added because they simplified the definition of such
overloads, and because Stroustrup liked the idea of allowing them in
other contexts as well.

Rick C. Hodgin

unread,
Apr 16, 2018, 4:11:09 PM4/16/18
to
I agree the reference syntax is cleaner, but I think it's more impor-
tant to have a visual cue on use as to the type.

Some editors do this by syntax highlighting the token differently.
I think that would be sufficient if it were present. Not all of
them do, and I wouldn't mind seeing something more consistently
indicating.

I really like the idea of the reference uses with the trailing
ampersand.

strA& + strB&

Would be fine with me. It would work on things like a pointer,
and allow only pointers and nonull pointers to be used. It would
document the necessity that a pointer must be nonull for uses in
cases where it's not a reference, but is a pointer that has al-
ready been validated, for example.

--
Rick C. Hodgin

Tim Rentsch

unread,
Apr 19, 2018, 12:09:32 AM4/19/18
to
Manfred <non...@invalid.add> writes:

> On 4/13/2018 4:12 PM, Tim Rentsch wrote:
>
>> Manfred <non...@invalid.add> writes:
>>
>>> On 4/10/2018 7:45 PM, Alf P. Steinbach wrote:
>>>
>>>> On 10.04.2018 19:22, Mr Flibble wrote:
>>>>
>>>>> On 10/04/2018 15:26, Rick C. Hodgin wrote:
>>>>>
>>>>>> What is the C++ reasoning for having both & and * types? Why not just
>>>>>> have * types?
>>>>>
>>>>> So you can refer to an object without using pointer semantics.
>>>>
>>>> That's right.
>>>>
>>>> Bjarne added references to support user-defined operators. Without
>>>> references they would be really ugly and not like built-in
>>>> operators.
>>>
>>> In fact it achieved a somewhat broader goal:
>>> At the time C++ was invented, some languages (notably C) used
>>> call-by-value argument evaluation, other (e.g. FORTRAN) used
>>> call-by-reference evaluation.
>>
>> I'm pretty sure FORTRAN used call by value-result, at least
>> in the FORTRAN IV era which is when I learned FORTRAN.
>
> My time with FORTRAN dates back a very long time ago (fortran 77 was
> the one I learned), so I'm a bit rusty, but I'm positive I was taught
> it was call by reference.

Yes, I expect that's right for fortran 77, and probably later
fortrans also. (It wasn't my intention to contradict you,
just to add to the conversation.)

I remember being taught (this was before 1977) that Fortran uses
call by value-result. I don't have as much confidence in my memory
being reliable as you seem to have in yours, hence "pretty sure". A
web search turned up these pages:

https://www.d.umn.edu/~rmaclin/cs5641/fall2004/Notes/Lecture13.pdf
http://pages.cs.wisc.edu/~fischer/cs536.s08/course.hold/html/NOTES/9.PARAMETER-PASSING.html

which say that some Fortrans used value-result (I think Fortran IV
is mentioned specifically on one of them). And of course arrays
are different (I didn't bother even to check what was said about
arrays).
0 new messages