Arrays passed by almost reference?

Travis Boucher boucher.travis at gmail.com
Thu Nov 5 06:28:25 PST 2009


dsimcha wrote:
> == Quote from Ali Cehreli (acehreli at yahoo.com)'s article
>> I haven't started reading Andrei's chapter on arrays yet. I hope I won't find
> out that the following behavior is expected. :)
>> import std.cstream;
>> void modify(int[] a)
>> {
>>     a[0] = 1;
>>     a ~= 2;
>>     dout.writefln("During: ", a);
>> }
>> void main()
>> {
>>     int[] a = [ 0 ];
>>     dout.writefln("Before: ", a);
>>     modify(a);
>>     dout.writefln("After : ", a);
>> }
>> The output with dmd 2.035 is
>> Before: [0]
>> During: [1,2]
>> After : [1]
>> I don't understand arrays. :D
>> Ali
> 
> This is one of those areas where the low-level details of how arrays are
> implemented arrays leak out.  This is unfortunate, but in a close-to-the-metal
> language it's sometimes a necessary evil.
> 
> (Dynamic) Arrays are structs that consist of a pointer to the first element and a
> length.  Essentially, the memory being pointed to by the array is passed by
> reference, but the pointer to the memory and the length of the array are passed by
> value.  While this may seem ridiculous at first, it's a tradeoff that allows for
> the extremely convenient slicing syntax we have to be implemented efficiently.
> 
> When you do the a[0] = 1, what you're really doing is:
> 
> *(a.ptr) = 1;
> 
> When you do the a ~= 2, what you're really doing is:
> 
> // Make sure the block of memory pointed to by a.ptr
> // has enough capacity to be appended to.
> a.length += 1;
> *(a.ptr + 1) = 2;
> 
> Realistically, the only way to understand D arrays and use them effectively is to
> understand the basics of how they work under the hood.  If you try to memorize a
> bunch of abstract rules, it will seem absurdly confusing.

main.a starts as:
struct {
   int length = 1;
   int *data = 0x12345; // some address pointing to [ 0 ]
}

inside of modify, a is:
struct { // different then main.a
    int length = 2;
    int *data = 0x12345; // same as main.a data [ 1, 2]
}

back in main:
struct { // same as original main.a
   int length = 1;
   int *data = 0x12345; // hasn't changed address, but data has to [ 1 ]
}


To get the expected results, pass a as a reference:

void modify(ref int[] a);



More information about the Digitalmars-d mailing list