当前位置: 代码迷 >> VC >> 关于if( (二>1) && (k=5) )的疑问
  详细解决方案

关于if( (二>1) && (k=5) )的疑问

热度:288   发布时间:2016-05-05 00:06:08.0
关于if( (2>1) && (k=5) )的疑问
我是学C#出生的,最近在看C语言.
遇到一个问题,如下:
int k=20;
if( (2>1)  && (k=5)  )
{
}

上面的k=5是一个赋值表达式,返回的不是Bool类型啊?为什么可以这样写呢???

C#中的写法是这样的,如下

if( (2>1)  && (k==5)  )
{
}
至少返回类型是Bool类型的,可以让人理解的.

请大神们帮忙解答,谢谢!
------解决方案--------------------
这就是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 不应该具有一个值。它的作用应该是“赋值”这种“动作”,而不应该具有任何“值”。即使牵强一点硬说它有值,它的值也应该是 void。这样一来 x = y = 0 和 if (y = 0) 就会因为“类型不匹配”而被编译器拒绝接受,从而避免了可能出现的错误。

仔细想想 x = y = 0 和 if (y = 0) 这样的写法给你带来了多少好处吧,几乎没有什么好。但它们带来的问题耗费了不知道多少人多少时间。这就是我为什么把它们叫做“小聪明”。
  相关解决方案