digitalmars.D.learn - Is this documented behaviour?
- John Colvin (21/21) Jul 23 2013 void foo(ref int a)
- Adam D. Ruppe (2/2) Jul 23 2013 There's nothing weird there because int b is a new variable, so
- John Colvin (3/5) Jul 23 2013 Sorry, I should have been more clear. It's the first case that
- Dicebot (3/5) Jul 23 2013 Why? '*aptr' is 'a' pretty much by definition of pointer
- John Colvin (5/10) Jul 23 2013 To be honest, I wasn't expecting foo(*aptr) to compile at all,
- monarch_dodra (9/20) Jul 24 2013 "Pass-by-Ref" is pretty much sugar for "pass-pointer-by-value".
- John Colvin (7/29) Jul 24 2013 I'm actually amazed how many years I've had the wrong conception
- Dicebot (7/9) Jul 24 2013 But there are no temporaries here. You seem to mix concepts of
- John Colvin (3/12) Jul 24 2013 nope, I get that. I was just confusing the basics of how pointers
- Jonathan M Davis (6/29) Jul 23 2013 There is no such thing as an "explicit temporary." You declared a new
- John Colvin (6/27) Jul 24 2013 Thanks for the explanations people, I have now fixed a rather
- Tyler Jameson Little (17/46) Jul 27 2013 To put the final nail in the coffin, this also works in C++:
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
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
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
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
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: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.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
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:"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.On Tuesday, 23 July 2013 at 17:03:52 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. It's clearly the right behaviour to allow it, but it took me by surprise at first.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 24 2013
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: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?!On Tuesday, 23 July 2013 at 17:06:37 UTC, Dicebot wrote:"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.On Tuesday, 23 July 2013 at 17:03:52 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. It's clearly the right behaviour to allow it, but it took me by surprise at first.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 24 2013
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
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:nope, I get that. I was just confusing the basics of how pointers work *facepalm*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
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
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
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: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!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 27 2013