Pointers or copies?

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Thu Dec 21 16:09:29 PST 2006


Chris Nicholson-Sauls wrote:
> Frits van Bommel wrote:
>> Chris Nicholson-Sauls wrote:
>>> void drop (T) (inout T[] haystack, size_t index)
>>> in {
>>>   assert(index < haystack.length, ".drop() called with index greater 
>>> than array length");
>>> }
>>> body {
>>>   if (index != haystack.length - 1) {
>>>     memmove(&(haystack[index]), &(haystack[index + 1]), T.sizeof * 
>>> (haystack.length - index));
>>>   }
>>>   haystack.length = haystack.length - 1;
>>> }
>>
>> Doesn't that move one element from beyond the end of the array?
>>
>> Array [0, 1, 2], drop element at index 1:
>>     memmove(&(array[1]), &(array[2]), int.sizeof * (3-1));
>> Moves 2 elements, starting at the 3rd element (element at index 2) of 
>> a 3-element array...
> 
> Doesn't seem to.  Illustrative program:
> 
> # import cashew .utils .array ;
> # import std           .stdio ;
> #
> # struct Foo {
> #   int[] alpha = [0, 1, 2],
> #         beta  = [3, 4, 5];
> # }
> #
> # void main () {
> #   Foo foo ;
> #
> #   writefln("foo.alpha == ", foo.alpha);
> #   writefln("foo.beta  == ", foo.beta );
> #
> #   foo.alpha.drop(1U);
> #
> #   writefln("foo.alpha == ", foo.alpha);
> #   writefln("foo.beta  == ", foo.beta );
> # }
> 
> For me this output:
> foo.alpha == [0,1,2]
> foo.beta  == [3,4,5]
> foo.alpha == [0,2]
> foo.beta  == [3,4,5]
> 
> Which seems to imply the data after alpha isn't being touched.  That 
> said, I'll try changing it anyhow.  Just in case.

How do you know it isn't touched? Just because it doesn't segfault 
doesn't mean it isn't accessing beyond array bounds...
In fact, as long as the int after alpha is readable (i.e. the memory is 
mapped) you won't see a difference with that code.

You'd probably see a difference if you kept a copy of alpha around and 
wrote that to output as well, though. (since the length of the copy 
doesn't get adjusted)
In fact, I just tried that and the last element of alpha is overwritten 
by the first element of beta. This shouldn't happen if memmove() is 
called with the correct parameters.

Another way to see this without keeping references to arrays being 
modified (which is arguably bad style) is the following:
Replace the last argument of the memmove call with
'T.sizeof * (haystack.length - index - 1)' and notice your code above 
gives the exact same result...



More information about the Digitalmars-d mailing list