newbie prob: referenced parameter only partially changed

Regan Heath regan at netmail.co.nz
Sun May 20 15:08:45 PDT 2007


J D Wrote:
> torhu Wrote:
> 
> > J D wrote:
> > > Love the language, from the description.  My first day trying to program in D.
> > > 
> > 
> > Nice to hear that.  Here's a page that I found very useful when learning D:
> > http://www.prowiki.org/wiki4d/wiki.cgi?LanguageSpecification/KeywordIndex
> > 
> > > I pass a dynamic char array to a function.  I modify the contents and set the .length to a smaller value (confirmed from within the routine).  When I return the array I passed in has the contents changed, but the length has not changed.  This seems inconsistent to me.
> > 
> > The array reference consists of the length, and a pointer to the data. 
> > What you get inside the function is just a copy of this reference, in 
> > other words a different reference to the same data.  Most of the time 
> > it's ok to just return a new reference if the function might change it.
> 
> I'll have to remember that, but it stil seems a wee bit inconsistent in that it changes the contents but not the length.

I agree, which is why we're all looking forward to testing Walters new 'const scope final' idea (see the digitalmars.D.announce group).

Just in case you haven't realised /why/ it happens I'll have a go at explaining exactly what's going on, if you've already got it feel free to ignore me ;)

void foo(char[] a) { a[0] = 'a'; a.length = a.length - 1;}
void main() { char[] b = "bbb"; foo(b); }

This code begins in main with an array reference called 'b', this reference is essentially a structure like so:

struct array {
  int length;
  void* ptr;
}

the length member of 'b' is 3 and ptr is the address of the location in memory where "bbb" is stored (plus a trailing null value because this is a string literal).

When you call 'foo' passing 'b' the compiler makes a copy of the reference/struct with the same values and passes this to 'foo'.  This is identical to what happens when you pass an 'int' or 'float' or 'struct', or even a pointer, you always get a copy of it (except of course when you use 'ref'/'inout' or even 'out').

Because you get a copy any changes made to 'length' only occur in the copy, not the original reference.  However, because ptr points to the same address in memory in both the original reference and the copy when you modify the data at that address you affect both references.

The exact same thing can be seen when you pass a pointer to a function, eg.

void foo(char* a) { a[0] = 'a'; a++; }
void main() { char* b = "bbb"; foo(b); }

The function foo gets a copy of the pointer so the "a++" has no effect on the original pointer "b", however as both pointers 'point' to the same memory address modifying the data there essentially affects both the original and copied pointers.

Regan Heath



More information about the Digitalmars-d mailing list