www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this documented behaviour?

reply "John Colvin" <john.loughran.colvin gmail.com> writes:
void foo(ref int a)
{
	a = 5;
}

void main()
{
	int a = 0;
	int* aptr = &a;
	
	foo(*aptr);
	assert(a == 5);
	
	a = 0;
	
	int b = *aptr;
	foo(b);
	assert(b == 5);
	assert(a == 0);
}

The fact that adding an explicit temporary changes the semantics 
seems weird to me.
Jul 23 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
There's nothing weird there because int b is a new variable, so 
assigning to it would not affect a in any case.
Jul 23 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 23 July 2013 at 16:40:53 UTC, Adam D. Ruppe wrote:
 There's nothing weird there because int b is a new variable, so 
 assigning to it would not affect a in any case.
Sorry, I should have been more clear. It's the first case that seems weird to me.
Jul 23 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 23 July 2013 at 17:03:52 UTC, John Colvin wrote:
 Sorry, I should have been more clear. It's the first case that 
 seems weird to me.
Why? '*aptr' is 'a' pretty much by definition of pointer dereferencing.
Jul 23 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 23 July 2013 at 17:06:37 UTC, Dicebot wrote:
 On Tuesday, 23 July 2013 at 17:03:52 UTC, John Colvin wrote:
 Sorry, I should have been more clear. It's the first case that 
 seems weird to me.
Why? '*aptr' is 'a' pretty much by definition of pointer dereferencing.
To be honest, I wasn't expecting foo(*aptr) to compile at all, with a "taking address of temporary" error or similar. It's clearly the right behaviour to allow it, but it took me by surprise at first.
Jul 23 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 23 July 2013 at 20:13:33 UTC, John Colvin wrote:
 On Tuesday, 23 July 2013 at 17:06:37 UTC, Dicebot wrote:
 On Tuesday, 23 July 2013 at 17:03:52 UTC, John Colvin wrote:
 Sorry, I should have been more clear. It's the first case 
 that seems weird to me.
Why? '*aptr' is 'a' pretty much by definition of pointer dereferencing.
To be honest, I wasn't expecting foo(*aptr) to compile at all, with a "taking address of temporary" error or similar. It's clearly the right behaviour to allow it, but it took me by surprise at first.
"Pass-by-Ref" is pretty much sugar for "pass-pointer-by-value". Basically, if you can take the address of the argument, then passing it is fair game. It's because you can't take the address of a temporary that you can't pass a temporary by ref (unless you are Microsoft Visual Studio, then there's no problem at all apparently 0_o). Of course, "*aptr" does not return a temporary, so passing that is fair game too.
Jul 24 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 24 July 2013 at 14:52:53 UTC, monarch_dodra wrote:
 On Tuesday, 23 July 2013 at 20:13:33 UTC, John Colvin wrote:
 On Tuesday, 23 July 2013 at 17:06:37 UTC, Dicebot wrote:
 On Tuesday, 23 July 2013 at 17:03:52 UTC, John Colvin wrote:
 Sorry, I should have been more clear. It's the first case 
 that seems weird to me.
Why? '*aptr' is 'a' pretty much by definition of pointer dereferencing.
To be honest, I wasn't expecting foo(*aptr) to compile at all, with a "taking address of temporary" error or similar. It's clearly the right behaviour to allow it, but it took me by surprise at first.
"Pass-by-Ref" is pretty much sugar for "pass-pointer-by-value". Basically, if you can take the address of the argument, then passing it is fair game. It's because you can't take the address of a temporary that you can't pass a temporary by ref (unless you are Microsoft Visual Studio, then there's no problem at all apparently 0_o). Of course, "*aptr" does not return a temporary, so passing that is fair game too.
I'm actually amazed how many years I've had the wrong conception of pointers in my head. Despite having written *ptr = val a million times, I was still imagining *ptr to be an rvalue i.e. read-from-this-address-and-return-value. How on earth did I never make the connection?!
Jul 24 2013
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 23 July 2013 at 20:13:33 UTC, John Colvin wrote:
 To be honest, I wasn't expecting foo(*aptr) to compile at all, 
 with a "taking address of temporary" error or similar.
But there are no temporaries here. You seem to mix concepts of "temporary" and "stack variable with deterministic lifetime". Taking address of a temporary is something like this: int foo() { return 42; } ... int* ptr = &(foo());
Jul 24 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 24 July 2013 at 15:03:33 UTC, Dicebot wrote:
 On Tuesday, 23 July 2013 at 20:13:33 UTC, John Colvin wrote:
 To be honest, I wasn't expecting foo(*aptr) to compile at all, 
 with a "taking address of temporary" error or similar.
But there are no temporaries here. You seem to mix concepts of "temporary" and "stack variable with deterministic lifetime". Taking address of a temporary is something like this: int foo() { return 42; } ... int* ptr = &(foo());
nope, I get that. I was just confusing the basics of how pointers work *facepalm*
Jul 24 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, July 23, 2013 18:34:51 John Colvin wrote:
 void foo(ref int a)
 {
 a = 5;
 }
 
 void main()
 {
 int a = 0;
 int* aptr = &a;
 
 foo(*aptr);
 assert(a == 5);
 
 a = 0;
 
 int b = *aptr;
 foo(b);
 assert(b == 5);
 assert(a == 0);
 }
 
 The fact that adding an explicit temporary changes the semantics
 seems weird to me.
There is no such thing as an "explicit temporary." You declared a new variable, and since int is a value type, of course any changes to that new variable had no effect on the int that was used to initialize it. And you can't use temporaries with ref parameters regardless. - Jonathan M Davis
Jul 23 2013
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 23 July 2013 at 16:34:54 UTC, John Colvin wrote:
 void foo(ref int a)
 {
 	a = 5;
 }

 void main()
 {
 	int a = 0;
 	int* aptr = &a;
 	
 	foo(*aptr);
 	assert(a == 5);
 	
 	a = 0;
 	
 	int b = *aptr;
 	foo(b);
 	assert(b == 5);
 	assert(a == 0);
 }

 The fact that adding an explicit temporary changes the 
 semantics seems weird to me.
Thanks for the explanations people, I have now fixed a rather worrying mistake in my programming knowledge: WHAT IT ACTUALLY MEANS TO DEREFERENCE A POINTER! Seriously, I've written programs in assembly and I still had it wrong. It's a wonder I ever wrote any correct code in my life.
Jul 24 2013
parent "Tyler Jameson Little" <beatgammit gmail.com> writes:
On Wednesday, 24 July 2013 at 15:14:16 UTC, John Colvin wrote:
 On Tuesday, 23 July 2013 at 16:34:54 UTC, John Colvin wrote:
 void foo(ref int a)
 {
 	a = 5;
 }

 void main()
 {
 	int a = 0;
 	int* aptr = &a;
 	
 	foo(*aptr);
 	assert(a == 5);
 	
 	a = 0;
 	
 	int b = *aptr;
 	foo(b);
 	assert(b == 5);
 	assert(a == 0);
 }

 The fact that adding an explicit temporary changes the 
 semantics seems weird to me.
Thanks for the explanations people, I have now fixed a rather worrying mistake in my programming knowledge: WHAT IT ACTUALLY MEANS TO DEREFERENCE A POINTER! Seriously, I've written programs in assembly and I still had it wrong. It's a wonder I ever wrote any correct code in my life.
To put the final nail in the coffin, this also works in C++: #include "stdio.h" void change(int & x) { x = 4; } int main(int argc, char** argv) { int a = 0; int* aptr = &a; change(*aptr); printf("%d\n", a); } TBH, I was also a bit surprised because I assumed *aptr as an rvalue created a temporary, but as you mentioned, that's not how it works in assembly, so it's wrong to think it would work differently in C/C++/D. Thanks for the post!
Jul 27 2013