www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - newbie prob: referenced parameter only partially changed

reply J D <digitalmars dresserfamily.org> writes:
Love the language, from the description.  My first day trying to program in D.

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.

I tried putting 'ref' before the 'char []' in the function declaration, but I
got a bunch of errors,although the docs said arrays are passed by reference by
default.  Can anyone help?
May 20 2007
next sibling parent Downs <default_357-line yahoo.de> writes:
J D wrote:
 Love the language, from the description.  My first day trying to program in D.
 
 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.
 
 I tried putting 'ref' before the 'char []' in the function declaration, but I
got a bunch of errors,although the docs said arrays are passed by reference by
default.  Can anyone help?

It helps to think of arrays as structs made of a length and a pointer (because that's what they are, really ^^ ) So when you pass an array in by value and change its contents, the length that you're changing belongs to a copy of the array that the function was called with. ref char[] should work, but that's a recent change and might not be supported by your compiler yet. Try inout instead of ref. Finally, can you paste your code? We can't help you properly until we can reproduce the problem. -- downs
May 20 2007
prev sibling parent reply torhu <fake address.dude> writes:
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 tried putting 'ref' before the 'char []' in the function declaration, but I
got a bunch of errors,although the docs said arrays are passed by reference by
default.  Can anyone help?

This should work. 'ref' was added not long ago, so maybe you compiler is too old. Try using 'inout' instead, which is an older alias for ref.
May 20 2007
parent reply J D <digitalmars dresserfamily.org> writes:
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 tried putting 'ref' before the 'char []' in the function declaration, but I
got a bunch of errors,although the docs said arrays are passed by reference by
default.  Can anyone help?

This should work. 'ref' was added not long ago, so maybe you compiler is too old. Try using 'inout' instead, which is an older alias for ref.

I am using gdc, and 'inout' worked so I guess it is not the newest. I tried installing dmd too. Which is better? What are the trade-offs? dmd would not compile the sample code. It complained of not being able to find libraries even though it was there. Thanks much for the help. I have a feeling you'll be hearing more from me. :)
May 20 2007
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"J D" <digitalmars dresserfamily.org> wrote in message 
news:f2qfpf$30d8$1 digitalmars.com...
 I'll have to remember that, but it stil seems a wee bit inconsistent in 
 that it changes the contents but not the length.

Think of it this way: void func(int* p) { p = realloc(p, 5); p[0] = 4; } int* p = new int[2]; p[0] = 2; func(p); printf("%d\n", p[0]); // prints 2 Of course, if you're not coming from C, this doesn't help either ;) But whenever you change the length of an array, it can possibly be reallocated and moved.
 I am using gdc, and 'inout' worked so I guess it is not the newest.

GDC is only up to DMD 1.004, so no, ref isn't there.
 I tried installing dmd too.  Which is better?  What are the trade-offs?

DMD is kept more up-to-date (it's the reference compiler after all), GDC is usually a bit behind. GDC is available on any platform that GCC is, DMD is only available on Windows and Linux. GDC is completely open-source, DMD has a proprietary backend, if you have any ethical qualms about that.
 dmd would not compile the sample code.  It complained of not being able to 
 find libraries even though it was there.

Don't know much about that :{ I think there may have been a topic about something like this recently on .learn or .bugs though..
May 20 2007
prev sibling parent reply Regan Heath <regan netmail.co.nz> writes:
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
May 20 2007
parent J D <digitalmars dresserfamily.org> writes:
OK then it's just more internals I need to memorize (which I'm more than used
to from using other languages).  It's not the monolithic object it seems to be
at first glance.  I can live with it.

Regan Heath Wrote:

 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

May 20 2007