我是学C#出生的,最近在看C语言.
遇到一个问题,如下:
int k=20;
if( (2>1) && (k=5) )
{
}
上面的k=5是一个赋值表达式,返回的不是Bool类型啊?为什么可以这样写呢???
C#中的写法是这样的,如下
if( (2>1) && (k==5) )
{
}
至少返回类型是Bool类型的,可以让人理解的.
请大神们帮忙解答,谢谢!
C C#
------解决方案--------------------
这就是C#比C++先进的地方(个人认为)了
99.9%的情况if( (2>1) && (k=5) )是错误的,程序员漏掉一个=号。C#会报编译错误,C++不会。
因为C++有隐式转换,在C++中
(2>1)返回true
(k=5)返回5,任何非0 int隐式转换成true
因此整个statement 结果为true.
还有类似
int i = 5;
if (i)
在C#中编译错误,必须写成 if (i != 0)
c++中允许,结果为true.
------解决方案--------------------
我想引用王垠的观点
http://www.yinwang.org/blog-cn/2013/03/15/language-design-mistake1/
赋值语句作为值
在几乎所有像 C,C++,Java 的语言里,赋值语句都可以被作为值。之所以设计成这样,是因为你就可以写这样的代码:
if (y = 0) { ... }
而不是
y = 0;
if (y) { ... }
程序好像缩短了一行,然而,这种写法经常引起一种常见的错误,那就是为了写 if (y == 0) { ... } 而把 == 比较操作少打了一个 =,变成了 if (y = 0) { ... }。很多人犯这个错误,是因为数学里的 = 就是比较两个值是否相等的意思。
不小心打错一个字,就让程序出现一个 bug。不管 y 原来的值是多少,经过这个“条件”之后,y 的值都会变成 0。所以这个判断语句会一直都为“假”,而且一声不吭的改变了 y 的值。这种 bug 相当难以发现。这就是另一个例子,说明片面追求短小带来的不应有的问题。
正确的做法是什么呢?在一个类型完备的语言里面,像 y=0 这样的赋值语句,其实是不应该可以返回一个值的,所以它不允许你写:
x = y = 0
或者
if (y = 0) { ... }
这样的代码。
x = y = 0 的工作原理其实是这样:经过 parser 它其实变成了 x = (y = 0)(因为 = 操作符是“右结合”的)。x = (y = 0) 这个表达式也就是说 x 被赋值为 (y = 0) 的值。注意,我说的是 (y = 0) 这整个表达式的值,而不是 y 的值。所以这里的 (y = 0) 既有副作用又是值,它返回 y 的“新值”。
正确的做法其实是:y = 0 不应该具有一个值。它的作用应该是“赋值”这种“动作”,而不应该具有任何“值”。