# Are Julia Arrays double pointers?

**URL:** <https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732>\
**Category:** Performance\
**Created:** [October 1, 2018, 12:44pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732 "2018-10-01T12:44:14Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacob](https://avatars.discourse-cdn.com/v4/letter/j/f1d935/32.png) [@jacob](https://discourse.julialang.org/u/jacob)\
**Post date:** [October 1, 2018, 12:44pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/1 "2018-10-01T12:44:14Z")

</div>

When you have a immutable struct

> struct A  
> a::Array{Float64, 1}  
> end  
> b = A([1,2,3])  
> then you can do A.a[2] = 5. Ok, I understand that this is possible as you just mutate the object which A.a is pointing to, you do not change it. You can’t do A.a = [1,2,3,4]. I also get that as A is immutable you can’t just change the pointer A.a.  
> But you can do push!(A.a, 4). push! of course doesn’t allocate new memory and change A.a every time it is called, but it sometimes will.

So you can change the pointer A.a.

Another experiment someone on slack did is this:  
array = ; println(pointer\_from\_objref(array))  
for i in 1:1000000 push!(array, 5) end  
println(pointer\_from\_objref(array)) # same memory address

This now leads to the conclusion that Julia Arrays are in fact pointers to pointers on the heap, and these pointers actually point to the content?

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [October 1, 2018, 12:58pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/2 "2018-10-01T12:58:16Z")

</div>

`ptr = pointer_from_objref(v::Array{Cint})` can be used as as `int**ptr` with `v[i]` stored at `ptr[0][i-1]`, and this is what you should pass to C-functions taking `int**`. For convenience, there is the function `pointer(v)`, returning `ptr[0]`.

Wrapping another `mutable struct A` around it makes it a triple pointer. Wrapping an immutable `struct A` around it makes it a compiler choice whether to allocate a heap-object (triple pointer) or just store the contents (double pointer) on the stack / in register.

In your immutable struct wrap case, `pointer_from_objref(b.a)` will remain forever unchanged, but `pointer(b.a)` may change when you push!/resize!.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 1, 2018, 1:02pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/3 "2018-10-01T13:02:15Z")

</div>

> [@jacob](#):
>
> This now leads to the conclusion that Julia Arrays are in fact pointers to pointers on the heap, and these pointers actually point to the content?

The `julia` array is defined here [https://github.com/JuliaLang/julia/blob/391f2dd2b5ac67da4a136673b1923d966b606439/src/julia.h#L166-L185](https://github.com/JuliaLang/julia/blob/391f2dd2b5ac67da4a136673b1923d966b606439/src/julia.h#L166-L185).

`pointer_from_objref` gives you a pointer to the Julia object (constant) while `pointer` gives you a pointer to the data (can change when e.g. resizing).

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 1, 2018, 1:18pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/4 "2018-10-01T13:18:06Z")

</div>

> [@foobar\_lv2](#):
>
> `ptr = pointer_from_objref(v::Array{Cint})` can be used as as `int**ptr` with `v[i]` stored at `ptr[0][i-1]` , and this is what you should pass to C-functions taking `int**` . For convenience, there is the function `pointer(v)` , returning `ptr[0]` .

Yes it is, but no you **must not** do this and `pointer` is by all mean **not** “for convenience”. In fact, you shouldn’t even use `pointer` in almost all cases when passing an array to C.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [October 1, 2018, 1:39pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/5 "2018-10-01T13:39:33Z")

</div>

Thanks, it appears I yet again underestimated the assumptions julia makes. Apart from the GC-preserve, what is the bad thing about passing `pointer_from_objref` or `pointer` to C?

The fact that the C-function might mistakenly believe that it is OK to write to `pointer_from_objref`, i.e. the `jl_array`? (which you nicely showed me is never OK for multidimensional arrays, thanks again!)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 1, 2018, 1:49pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/6 "2018-10-01T13:49:14Z")

</div>

You can pass these values just fine but in almost no case should you get these values by calling these functions directly. You should use the appropriate argument type in ccall to do this automatically. There’s certainly ways to call these directly and correctly but that’s something you shouldn’t just recommend to everyone.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 1, 2018, 1:50pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/7 "2018-10-01T13:50:19Z")

</div>

And the fact that the first element of the array struct is the pointer is implementation detail that you have no reason to rely on.

---

<div class="post-metadata">

**Author:** ![jacob](https://avatars.discourse-cdn.com/v4/letter/j/f1d935/32.png) [@jacob](https://discourse.julialang.org/u/jacob)\
**Post date:** [October 1, 2018, 2:03pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/8 "2018-10-01T14:03:03Z")

</div>

Thank you very much for the very clear answer, that already helps. Do I understand it right now:  
(1) In general an Array here is a int\*\*, so when I do a = zeros(N) I actually have to allocate N_int64 somewhere and also some space for the Array header that points to the N_int64.  
(2) A mutable struct will always have pointers to all of its fields and they are all heap-allocated  
(3) An immutable struct can also be as the above but if I for example create an immutable struct inside a function and it sees that nobody else will need access to that field and the immutable struct goes out of scope soon anyways, Julia may optimize it away and store it directly to the stack

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 1, 2018, 2:12pm UTC](https://discourse.julialang.org/t/are-julia-arrays-double-pointers/15732/9 "2018-10-01T14:12:07Z")

</div>

> [@jacob](#):
>
> In general an Array here is a int\*\*

No.

> [@jacob](#):
>
> also some space for the Array header that points to the N\* int64

Yes, just not necessarily `Int64`

> [@jacob](#):
>
> A mutable struct will always have pointers to all of its fields and they are all heap-allocated

No. There’s no layout difference between mutable struct and immutable ones with the same field types.

> [@jacob](#):
>
> it sees that nobody else will need access to that field and the immutable struct goes out of scope soon anyways, Julia may optimize it away and store it directly to the stack

There’s very few case where it’ll actually be on the stack. In most cases the struct will just be completely gone and it’s not an optimization that has anything to do with the mutability of the type.
