Think about what it means for an object to be mutable: it means if you change a field of the object, then all references to the object must see the change. This means that an array of mutable objects is not like an array of C structs, it is like an array of pointers to C structs.
For example, consider:
type Foo
x::Int
end
a = [Foo(3), Foo(15)]
b = a[2]
At this point, a[2] and b are essentially "pointers" to the same Foo(15) object in memory. If we do
b.x = 17
then a[2].x will yield 17 as well. To achieve this functionality, a Julia Array{Foo} must be (and is) internally equivalent to an array of some kind of pointers to Foo objects.
In contrast, consider an immutable type:
type Bar
x::Int
end
a = [Bar(3), Bar(15)]
b = a[2]
Because the Bar(15) object cannot be mutated, the compiler is free to make a copy of the underlying bits when assigning b = a[2], rather than making them a pointer to the same object. Furthermore, since it no longer needs to keep a unique blob of bits in memory for each Bar object, Julia can store an Array{Bar} as an array of the underlying data, equivalent to an array of C structs (and, in this case, equivalent in storage to an Array{Int}).
This does not mean that you can't change the contents of the array a, however. You cannot do a[2].x = 17 (the compiler will give an error since Bar is immutable), but you are perfectly free to do
a[2] = Bar(17)
That is, while you cannot change an existing Bar object to have different contents, you can replace one Bar object with another in an array.
This distinction, and the existence of immutable types, is really crucial to have efficient code for arrays (and other data structures) of user-defined objects. It is easy for a C programmer to understand this, because working with an array of structs is almost always going to be more efficient (in both space and speed) than working with an array of pointers to structs. At the same time, mutable data structures are useful too, so Julia needs to have both.