3

为什么

if (x) {
    f();
}

f()如果x是空字符串则调用""

bool falseD中的空字符串不应该像在Python中那样隐式转换为空数组时(在D中)吗?

更新:我解决了这个问题。我错误地颠倒了推理逻辑。幸运的是,聪明的 D 头脑无论如何都明白我的意思;)

4

3 回答 3

10

条件、if语句和循环bool由编译器强制转换。所以,

if(x) {...}

变成

if(cast(bool)x) {...}

在数组的情况下,强制转换bool为等同于测试其ptr属性是否为 not null。所以,它变成

if(x.ptr !is null) {...}

在数组的情况下,这实际上是一个非常糟糕的测试,因为null数组被认为与空数组相同。因此,在大多数情况下,您并不关心数组是否null存在。数组本质上是一个结构,看起来像

struct Array(T)
{
    T* ptr;
    size_t length;
}

The == operator will check whether all of the elements referred to by ptr are equal, but if length is 0 for both arrays, it doesn't care what the value of ptr is. That means that "" and null are equal (as are [] and null). However, the is operator explicitly checks the ptr properties for equality, so "" and null won't be the same according to the is operator, and whether a particular array which is empty has a null ptr depends on how its value was set. So, the fact that an array is empty really says nothing about whether it's null or not. You have to check with the is operator to know for sure.

The result of all this is that it's generally bad practice to put an array (or string) directly in a condition like you're doing with

if(x) {...}

Rather, you should be clear about what you're checking. Do you care whether it's empty? In that case, you should check either

if(x.empty) {...}

or

if(x.length == 0} {...}

Or do you really care that it's null? In that case, use the is operator:

if(x is null) {...}

The behavior of arrays in conditions is consistent with the rest of the language (e.g. pointer and reference types are checked to see whether they're null or not), but unfortunately, in practice, such behavior for arrays is quite bug-prone. So, I'd advise that you just don't ever put an array by itself in the condition of an if statement or loop.

于 2013-09-02T05:43:12.647 回答
4

数组的默认转换查看.ptr,这意味着只有默认的初始化数组(或显式设置为 null)评估为 false

作为附加效果 D 中的字符串文字被\0终止,这意味着("")[0] == '\0'不能("").ptr为空(这将导致段错误)

IMO 它应该查看长度,您可以在需要时使用 ptr

于 2013-09-01T23:15:56.890 回答
3

当我尝试它时,它会...

void main() {
    import std.stdio;
    string s = "";
    if(s)
            writeln("true"); // triggered
}

如果是“字符串 s = null;” (这是默认初始化),它没有,因为 null 转换为 false,但是 "" 在我的计算机上是可以的。你确定它不为空吗?

顺便说一句,如果你想测试(非)空性,我更喜欢这样做的方式是 if(x.length) 和 if(x.length == 0)。这些对“”和 null 都有效,然后如果您特别想要 null,请执行 if(x is null)。它只是更清楚一点,特别是因为 "" 和 null 在 D 中的许多其他上下文中是可以互换的。

于 2013-09-01T22:34:02.760 回答