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.