Checking if a string is null

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Wed Jul 25 10:01:57 PDT 2007


Regan Heath wrote:
>>> I'm in the 'distinguishable' camp.  I can see the merit.  At the very 
>>> least it should be consistent!
>>
>> They *are* distinguishable. That's why above code returns different 
>> results for the 'is' comparison...
> 
> True.  I guess what I meant to say was I'm in the '3 distict states' 
> camp (which may be a camp of 1 for all I know).  See my reply to 
> digitalmars.D for a definition of the 3 states.
> 
>> I for one am perfectly fine with "cast(char[]) null" meaning ".length 
>> == 0 && .ptr == null" 
> 
> Same here.
> 
>  > and with comparisons of arrays using == and friends
>> only inspecting the contents (not location) of the data.
> 
> I don't think an empty string (non-null, length == 0) should compare 
> equal to a non-existant string (null, length == 0).  And vice-versa.
> 
> The only thing that should compare equal to null is null.  Likewise an 
> empty array should only compare equal to another empty array.
 >
 > My reasoning for this is consistency, see at end.

Since null arrays have length 0, they *are* empty arrays :P.

> Aside: If the location and length are identical you can short-circuit 
> the compare, returning true and ignoring the content, this could save a 
> bit of time on comparisons of large arrays.

At least with that last paragraph I can agree ;)


Now, about this:

> All that I would like changed is for the compare, in the case of length 
> == 0, to check the data pointers, eg.
> 
>  > int opEquals(T)(T[] u, T[] v) {
>  >     if (u.length != v.length) return false;
>       if (u.length == 0) return (u.ptr == v.ptr);
>  >     for (size_t i = 0; i < u.length; i++) {
>  >         if (u[i] != v[i]) return false;
>  >     }
>  >     return true;
>  > }
> 
> This should mean "" == "" but not "" == null, likewise null == null but 
> not null == "".

Let's look at this code:
---
import std.stdio;

void main()
{
     char[][] strings = ["hello world!", "", null];

     foreach (str; strings) {
         auto str2 = str.dup;
         if (str == str2)
             writefln(`"%s" == "%s" (%s, %s)`, str, str2, str.ptr, 
str2.ptr);
         else
             writefln(`"%s" != "%s" (%s, %s)`, str, str2, str.ptr, 
str2.ptr);
     }
}
---
The output is currently (on my machine):
=====
"hello world!" == "hello world!" (805BE60, F7CFBFE0)
"" == "" (805BE78, 0000)
"" == "" (0000, 0000)
=====
Your change would change the second line (even if it actually allocated 
a new empty string like you probably want instead of returning null). 
How would that be consistent in any way?
(Same goes for other ways to create different-ptr empty strings)

What you might have meant on that extra line might be more like:
---
        if (u.length == 0) return ((u.ptr is null) == (v.ptr is null));
---
which will return true if both .ptr values are null or both are non-null.


More information about the Digitalmars-d-learn mailing list