Empty Array is Null?

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Wed Mar 19 09:20:01 PDT 2008


Steven Schveighoffer wrote:
> "Brian White" wrote
>> char[] array = "".dup;
>> assert(array !is null);
>>
>> This will exit because the assert condition is false.
>>
>> Why is that?
> 
> Here is my guess:
> 
> The compiler does not allocate a piece of memory for "", and so the array 
> struct for it looks like:
> 
> { ptr = null, length = 0 }

Sorry, but your guess is wrong:
---
urxae at urxae:~/tmp$ cat test.d
import std.stdio;

void main() {
     writefln("%s", "".ptr);
}
urxae at urxae:~/tmp$ dmd -run test.d
805C41C
---

> If you dup this, it gives you the same thing (no need to allocate an array 
> of size 0).

Since as I mentioned above the input wasn't null, so it's not "the same 
thing". Otherwise, this is correct (including the reason given; actually 
allocating 0 bytes is pretty useless).

The fact that empty_arr.dup returns null has been the topic of some 
discussion in the newsgroups IIRC, but the fact is that it's equivalent 
to allocating a zero-byte array on the heap in the most important aspects:
* The returned array has the correct length.
* All elements of the returned array are identical to the original 
array. [1]
* All of the returned array's elements can be freely modified without 
modifying the original array. [1]
* Changing any of the original elements doesn't change the returned 
array. [1]
* Appending anything to the returned value doesn't risk changing 
anything previously allocated (as the GC will allocate a new block of 
memory when appending to a non-gc-allocated array; which includes null 
arrays).

On top of all that, it's also very efficient since it doesn't require 
any allocation (at least, until anything is appended onto it).
The *only* property it doesn't have that 'normal' .dups do have is that 
normal .dups return unique non-null values. The only ways to even detect 
that are by 'is'-comparing to null (or a null-valued array) or 
(implicitly or explicitly) casting it to a boolean. All other behavior 
is completely consistent.
The discussion on the NGs was, IIRC, between those who considered 'null' 
to mean "no string" while considering other empty strings as "empty 
string" and those who just don't see any reason to explicitly 
distinguish between the two. In the end, I believe, it came down to 
"Walter is in the latter camp".


[1]: These are trivially true since having no elements that can be read 
or written means they don't actually require anything for empty arrays.

> Now, here is the weird part.  The compiler does some magic with arrays.  If 
> you are comparing an array with null, it changes the code to actually just 
> compare the array pointer to null.  So, the the following code:
> 
> array !is null
> 
> is translated to:
> 
> array.ptr !is null
> 
> And this is why the program fails the assert.

Actually, if you compare an array to null (using 'is') DMD performs an 
'or' instruction on the .ptr and .length and tests for the flag that it 
sets if the result is zero. This is just an optimization; this is 
equivalent to checking if both .ptr and .length are 0 (though presumably 
faster, since it's a single instruction that doesn't even implement full 
comparison).

> The sucky part about all this is that if you have an empty array where the 
> pointer is NOT null, then you get a different result (that array is not 
> considered to be null)

Actually, 'array == null' should return true for any empty array. 
Testing arrays with 'is' explicitly requests comparing .ptr and .length 
directly, not paying any attention to the contents; 'is' checks for 
identity, '==' for equivalence.

> So an array is null ONLY if the pointer is null.  An array is empty if the 
> length is 0.  If you want to check for an empty array, just check that the 
> length is 0.  If you want to make sure that the pointer is null (which 
> implies the length is 0), then check against null.

Other ways to check for an empty array are 'arr == ""' or 'arr == null' 
  (using '==' instead of 'is')


More information about the Digitalmars-d-learn mailing list