Beachhouse
Beachhouse

Reputation: 5052

Clarification on ZVals

I was reading this: http://www.dereleased.com/2011/04/27/the-importance-of-zvals-and-circular-references/

And there's an example that lost me a bit.

$foo = &$bar;
$bar = &$foo;
$baz = 'baz';

$foo = &$baz;

var_dump($foo, $bar);
/*
string(3) "baz"
NULL
*/

If you’ve been following along, this should make perfect sense. $foo is created, and pointed at a ZVal location identified by $bar; when $bar is created, it points at the same place $foo was pointed. That location, of course, is null. When $foo is reassigned, the only thing that changes is to which ZVal $foo points; if we had assigned a different value to $foo first, then $bar would still retain that value.

I learned to program in C. I understand that PHP is different and it uses ZVals instead of memory locations as references. But when you run this code:

$foo = &$bar;
$bar = &$foo;

It seems to me that there would be two ZVals. In C there would be two memory locations (and the values would be of the opposite memory location).

Can someone explain?

Upvotes: 4

Views: 439

Answers (1)

deceze
deceze

Reputation: 522332

It mostly comes down to how the symbol table works. It's a table with two sides:

symbol name  |  value
-------------+-------
             |

The fun thing is that a value can be assigned more than one name:

symbol name  |  value
-------------+-------
foo, bar     | 'baz'

When assigning to a symbol using =, the value side of the table is changed:

$baz = 42;

symbol name  |  value
-------------+-------
baz          | 42

When assigning using =&, the symbol name side is moved to wherever the value is:

$foo =& $baz;

symbol name  |  value
-------------+-------
baz, foo     | 42

So in your example, starting from scratch:

$foo =& $bar;
($bar does not exist, is null, which is implicitly created,
 $foo is pointed to where the implicitly created $bar points)

symbol name  |  value
-------------+-------
foo, bar     | null


$bar = &$foo;
(no real change, $bar is pointed to where $foo is pointing)

symbol name  |  value
-------------+-------
foo, bar     | null


$baz = 'baz';

symbol name  |  value
-------------+-------
foo, bar     | null
baz          | 'baz'


$foo = &$baz;
($foo is pointed to where $baz is pointing)

symbol name  |  value
-------------+-------
bar          | null
baz, foo     | 'baz'

Upvotes: 7

Related Questions