Pointers or copies?
Chris Nicholson-Sauls
ibisbasenji at gmail.com
Fri Dec 22 06:41:03 PST 2006
Frits van Bommel wrote:
> 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.
Well, there we are then. :)
> 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...
Actually, this is exactly what I have done. Its in the repository now.
-- Chris Nicholson-Sauls
More information about the Digitalmars-d
mailing list