Checking if a string is null
Frits van Bommel
fvbommel at REMwOVExCAPSs.nl
Wed Jul 25 06:05:25 PDT 2007
Regan Heath wrote:
> Max Samukha wrote:
>> Using '== null' and 'is null' with strings gives odd results (DMD
>> 1.019):
>>
>> void main()
>> {
>> char[] s;
>>
>> if (s is null) writefln("s is null");
>> if (s == null) writefln("s == null");
>> }
>>
>> Output:
>> s is null
>> s == null
>>
>> ----
>>
>> void main()
>> {
>> char[] s = "";
>>
>> if (s is null) writefln("s is null");
>> if (s == null) writefln("s == null");
>> }
>>
>> Output:
>> s == null
>>
>> ----
>>
>> Can anybody explain why s == null is true in the second example?
>
> Not I, it's inconsistent IMO and it gets worse:
>
> import std.stdio;
>
> void main()
> {
> foo(null);
> foo("");
> }
>
> void foo(string s)
> {
> writefln(s.ptr, ", ", s.length);
> if (s is null) writefln("s is null");
> if (s == null) writefln("s == null");
> if (s < null) writefln("s < null");
> if (s > null) writefln("s < null");
> if (s <= null) writefln("s <= null");
> if (s >= null) writefln("s < null");
> writefln("");
> }
>
> Output:
> 0000, 0
> s is null
> s == null
> s <= null
> s < null
>
> 415080, 0
> s == null
> s <= null
> s < null
>
> So, "" is < and == null!?
> and <=,== but not >=!?
As Max said, you forgot to update some writeflns. The output of the
corrected version is:
===
0000, 0
s is null
s == null
s <= null
s >= null
805BEF0, 0
s == null
s <= null
s >= null
===
Seems perfectly consistent to me. Anything with an equality comparison
(==, <=, >=) is true in both cases, and 'is' is only true when the
pointer as well as the length is equal.
> This all boils down to the empty vs null string debate where some people
> want to be able to distinguish between them and some see no point.
>
> 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...
I for one am perfectly fine with "cast(char[]) null" meaning ".length ==
0 && .ptr == null" and with comparisons of arrays using == and friends
only inspecting the contents (not location) of the data.
Now, about comparisons: array comparisons basically operate like this:
---
int opEquals(T)(T[] u, T[] v) { // bah to int return type
if (u.length != v.length) return false;
for (size_t i = 0; i < u.length; i++) {
if (u[i] != v[i]) return false;
}
return true;
}
int opCmp(T)(T[] u, T[] v) {
size_t len = min(u.length, v.length)
for (size_t i = 0; i < len; i++) {
if (auto diff = u[i].opCmp(v[i])) {
return diff;
}
}
return cast(int)u.length - cast(int)v.length;
}
---
(Taken from object.TypeInfo_Array and converted to templates instead of
void*s + casting + element TypeInfo.{equals/compare} for readability)
Since both the null string and "" have .length == 0, that means they
compare equal using those methods (having no contents to compare and
equal length)
This is all perfectly consistent (and even useful) to me...
More information about the Digitalmars-d-learn
mailing list