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