On Tue, Mar 25, 2014 at 6:32 PM, Keith Mason <desc...@gmail.com> wrote:

> Why not foos[1].bar instead of the 'convert / unsafe_load' code?


Because I wanted to show that the values are stored inline, rather than
heap allocated. That may have been clear to me but perhaps not so clear to
anyone else. Consider, for comparison, the mutable version of the same code:

julia> type Foo
         bar::Int
         baz::Float64
       end

julia> foos = Array(Foo,10)
10-element Array{Foo,1}:
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef

julia> foos[1] = Foo(1,2)
Foo(1,2.0)

julia> p = convert(Ptr{Int}, pointer(foos))
Ptr{Int64} @0x00007ff47514f030

julia> unsafe_load(p,1)
140687914392808

julia> unsafe_load(p,2)
0


There are a number of differences, all stemming from the fact that mutable
Foos must be individually heap allocated, rather than stored inline in the
array. Thus, an uninitialized slot in an Array{Foo} is #undef (null
pointers under the hood), rather than whatever junk happens to be the
memory that is allocated, as happens in the immutable version. When you get
the first 64-bit value at the offset of the array, you get a pointer to a
heap-allocated Foo value, rather than the data of that Foo value. The next
value after that is a null pointer. We can poke a bit further by following
the pointer:

julia> pp = convert(Ptr{Int},unsafe_load(p,1))
Ptr{Int64} @0x00007ff475295ce8

julia> unsafe_load(pp,1)
140687913054080

julia> unsafe_load(pp,2)
1

julia> unsafe_load(pp,3)
4611686018427387904


The first 64-bit value at the pointer location are a type tag indicating
what kind of value this thing is; the second and third 64-bit blobs are the
values of the .bar and .baz fields.

Reply via email to