What's the point of static arrays ?
stanislav.blinov at gmail.com
Fri Jul 10 11:13:51 UTC 2020
On Friday, 10 July 2020 at 10:13:23 UTC, wjoe wrote:
> So many awesome answers, thank you very much everyone!
> Less overhead,
> Using/needing it to interface with something else, and
> Efficiency are very good points.
> However stack memory needs to be allocated at program start. I
> don't see a huge benefit in allocation speed vs. heap
> pre-allocation, or is there?
Stack is allocated by the OS for the process when it's started.
Reserving space for stack variables, including arrays, is
effectively free, since the compiler assigns offsets statically
at compile time.
> I mean 1 allocation vs 2 isn't going to noticeably improve
> overall performance.
A GC allocation is way more complex than a mere bump-the-pointer.
If your program is trivial enough you may actually find that one
extra GC allocation is significant in its runtime. Of course, if
you only ever allocate once and your program runs for ages, you
won't really notice that allocation.
> What happens here exactly ?
int slice = a;
assert(slice.ptr == &a);
assert(slice.length == 10);
assert(a.sizeof == 10 * int.sizeof); // 40
assert(slice.sizeof == (int).sizeof); // 16 on 64 bit
> I read the chapters in Ali's book (thank you very much for such
> a great book, Ali) on arrays and slicing prior to asking this
> question and I came to the following conclusion:
> Because a static array is pre-allocated on the stack,
> doesn't have a pointer/length pair,
> is addressed via the stack pointer, and
> due to the fact that a slice is a pointer/length pair
> and because a slice is technically the meta data of a dynamic
> array, a view into (part) of a dynamic array,
No. A slice is just a pointer/length pair - a contiguous view
into *some* memory, regardless of where that memory came from:
void takeASlice(scope void data) // can take any slice since
any slice converts to void
writefln("%x %d", data.ptr, data.length);
takeASlice(a); // a
takeASlice(a[1 .. $-1]); // a[1 .. 9]
float x, y, z;
float dx, dy, dz;
takeASlice((&s)[0 .. 1]); // Slicing a pointer, not @safe but can
takeASlice(new int); // Array, GC allocation
takeASlice([1, 2, 3, 4]); // Array literal, may or may not be
`takeASlice` has no knowledge of where the memory came from.
Dynamic arrays only ever come into the picture if you try to
manipulate the slice itself: resize it, append to it, etc.
> that it's not possible to slice a static array because the
> slice would technically be akin to a dynamic array and hence be
Incompatible to what?
int a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a[0 .. 2] = a[2 .. 4];
assert(a == 3);
assert(a == 4);
int b = void;
b = a;
assert(b == [3, 4, 3, 4, 5, 6, 7, 8, 9, 10]);
> struct SuperSpecializedArray(T, size_t S) if (S > 0)
> T[S] elements;
> struct SuperSpecializedArrayRange
> typeof(elements) e;
> this(SuperSpecializedArray a)
> e = a.elements; // copies
> // ...
> Upon creation of a SuperSpecializedArrayRange, the array is
> copied, but more importantly, data which may not ever be needed
> is copied and that's supposed to be a big selling point for
> ranges - only ever touching the data when it's requested - am I
> wrong ?
Ranges need not be lazy. They can be, and most of them should be
indeed, but they need not be. And, as you yourself point out, in
your case `e` can just be a slice, and your range becomes lazy.
More information about the Digitalmars-d-learn