Array start index

Bastiaan Veelo via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Feb 7 02:11:52 PST 2017


On Monday, 6 February 2017 at 23:42:55 UTC, Ali Çehreli wrote:
> Then you use _ptr when indexing:
>
>     // Support e = arr[5];
>     ref T opIndex(ptrdiff_t index) {
>         assert(index >= first);
>         assert(index <= last);
>         return *(_ptr + index);
>     }
>
> Ali

Thank you very much for your time. Sadly this gives me an access 
violation. The traceback doesn't seem right though, as it seems 
to jump to opIndexAssign from where opIndex is used. If I'm not 
mistaken, I have confirmed that _ptr is a valid address, see 
below. We do not need to take measures against the GC?

- Bastiaan.


On Windows:

rdmd -main -unittest -debug -g source\epcompat\array.d

object.Error@(0): Access Violation
----------------
0x00402057 in void epcompat.array.__unittestL81_1() at 
C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(88)
0x0040465C in void epcompat.array.__modtest() at 
C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(39)
0x0040A455 in int 
core.runtime.runModuleUnitTests().__foreachbody1(object.ModuleInfo*)
0x0040C007 in int object.ModuleInfo.opApply(scope int 
delegate(object.ModuleInfo*)).__lambda2(immutable(object.ModuleInfo*))
0x00406808 in _d_run_main
0x004046D4 in main at 
C:\SARC\Pascal2017\D\epcompat\source\epcompat\array.d(7)
0x004225DD in mainCRTStartup
0x779C62C4 in BaseThreadInitThunk
0x77B50FD9 in RtlSubscribeWnfStateChangeNotification
0x77B50FA4 in RtlSubscribeWnfStateChangeNotification

The complete source:

module epcompat.array;

// Test with rdmd -main -unittest -debug -g 
source\epcompat\array.d

alias StaticArray_offset StaticArray;

/*****************
  * A fixed-length array with an index that runs from $(D_PARAM 
first)
  * to $(D_PARAM last) inclusive.
  *
  * Implemented by means of an offset pointer.
  */
struct StaticArray_offset(T, ptrdiff_t first, ptrdiff_t last) {
     T[last - first + 1] _payload;
     T* _ptr;

     void init() {
         assert( first < cast(size_t)_payload.ptr);              
// Address space underrun.
         assert(-first < size_t.max - cast(size_t)_payload.ptr); 
// Address space overrun.
         this._ptr = _payload.ptr - first;
     }

     size_t length() {
         return _payload.length;
     }

     // Support e = arr[5];
     ref T opIndex(ptrdiff_t index) {
         assert(index >= first);
         assert(index <= last);
         return *(_ptr + index);
     }

     // Support arr[5] = e;
     void opIndexAssign(U : T)(auto ref U value, ptrdiff_t index) {
         assert(index >= first);
         assert(index <= last);
         *(_ptr + index) = value;
     }   // Line 39

     // Support foreach(e; arr).
     int opApply(scope int delegate(ref T) dg)
     {
         int result = 0;

         for (int i = 0; i < _payload.length; i++)
         {
             result = dg(_payload[i]);
             if (result)
                 break;
         }
         return result;
     }

     // Support foreach(i, e; arr).
     int opApply(scope int delegate(ptrdiff_t index, ref T) dg)
     {
         int result = 0;

         for (int i = first; i <= last; i++)
         {
             result = dg(i, *(_ptr + i));
             if (result)
                 break;
         }
         return result;
     }

     // Write to binary file.
     void toFile(string fileName)
     {
         import std.stdio;
         auto f = File(fileName, "wb");
         if (f.tryLock)
         {
             f.rawWrite(_payload);
         }
     }
}

unittest {
     StaticArray!(int, -10, 10) arr;
     assert(arr.length == 21);

     foreach (ref e; arr)
         e = 42;

     assert(arr[-10] == 42); // Line 88
     assert(arr[0]   == 42);
     assert(arr[10]  == 42);

     foreach (i, ref e; arr)
         e = i;

     assert(arr[-10] == -10);
     assert(arr[0]   ==   0);
     assert(arr[5]   ==   5);
     assert(arr[10]  ==  10);

     arr[5] = 15;
     assert(arr[5]   == 15);
}



More information about the Digitalmars-d-learn mailing list