What's the point of static arrays ?

Ali Çehreli acehreli at yahoo.com
Thu Jul 9 14:30:48 UTC 2020


On 7/9/20 5:12 AM, wjoe wrote:

> Considering the many downsides why would I ever want to choose a static 
> over a dynamic array ?
> 

In addition to what others said, dynamic arrays can be more expensive 
both in space and time.

Time: Dynamic array elements are accessed through an extra pointer 
compared to static arrays. Depending on the usage pattern of the data, 
that extra indirection may be slower (e.g. due to the extra load on the 
CPU's cache).

Space: Every dynamic array is represented by the pair of one pointer 
(void*) one length (size_t) e.g. 2 * 8 = 16 bytes on a 64-bit system. 
Assuming the array is just 3 floats, which is a common type used for 
RGB, 3D coordinates, etc. (3 * 4 = 12 bytes), then those 16 bytes are 
more than the data itself.

I wrote the following program (as a fun morning exercise, before coffee 
:o) ) to display bytes used by different kinds of variables:

import std.stdio;
import std.range;
import std.algorithm;
import std.traits;

size_t bytesUsed(T)(T var) {
   static if (isDynamicArray!T) {
     enum dynamicArrayOverhead = (void[]).sizeof;
     // Double check:
     static assert (dynamicArrayOverhead == size_t.sizeof + (void*).sizeof);

     return dynamicArrayOverhead + var.map!(element => 
bytesUsed(element)).sum;

   } else static if (isAssociativeArray!T) {
     static assert (false, "I don't know the implementation of AAs.");

   } else static if (is (T == struct)) {
     // BUG: Ignores alignment
     size_t total;
     foreach (member; var.tupleof) {
       total += bytesUsed(member);
     }
     return total;

   } else static if (is (T == class)) {
     // BUG: Ignores alignment
     size_t total;
     foreach (member; var.tupleof) {
       total += bytesUsed(member);
     }
     enum classOverhead = (void*).sizeof * 2;
     return classOverhead + total;

   } else {
     return var.sizeof;
   }

// BUG: union?
}

unittest {
   struct S {
     int[] arr;
     void* ptr;
   }
   assert(bytesUsed(S([1, 2, 3])) == size_t.sizeof + (void*).sizeof + 3 
* int.sizeof + 8);
}

void info(alias var)() {
   writefln!"'%s' is %s and uses %s bytes."(var.stringof, 
typeof(var).stringof, bytesUsed(var));
}

void main() {
   // This is an efficient data structure:
   alias Color = float[3]; // red, green, blue
   alias DayColors = Color[7];

   // Comparing it to the dynamic array equivalent:
   DayColors a;
   auto b = makeDayColors();
   info!a;
   info!b;
}

float[] makeColor() {
   // Syntax confusion alert: Return type is *not* a static array. :/
   return new float[3];
}

float[][] makeDayColors() {
   float[][] result = new float[][7];
   foreach (ref e; result) {
     e = makeColor();
   }
   return result;
}

Ali


More information about the Digitalmars-d-learn mailing list