Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2314904
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: WINDOWS

2009-01-21 22:01:42

各种原因, 总会导致在程序中你希望把一个 if 语句中的条件永远置为true为false, 比如为了测试的目的强制执行.

最容易想到的:
if(  true || complex_condition )

不管 complex_condition 是什么, 前面的true || 会让它永远为真, 而
if( false && (complex_condition) )
则永远为假, 注意要把 (complex_condition) 用括号包围起来, 否则结果未必一定是false, 如
if( false && 3 < 2 || 2 > 1)
如果对 3 < 2 || 2> 1 不加理会, 只是把false && 放在前面, 是有漏洞的.

事情并没有就此这么简单.

我坚持使用编译器的最高等级的警告, 并且把所有警告视为错误, 以后我也会一直坚持这一原则.

这样一来, 前面的bool 表达式就是永远为true为永远为false, 而一个这样的表达式出现在程序中往往表明一个潜在的逻辑错误, 所以编译器对这面的语句给出一条警告:
if(true)
{
   puts("Yes");
}
test.cpp(183) : warning C4127: conditional expression is constant

(这一警告只有/W4 时才给出)

这样一来, 直接使用true / false 或1, 0 这样的方法就不行了. 如何在C库中找出一个优雅的无副作用的最简单的true/false 语句, 同时绕过上述的警告?

在C#中我最先有这样的需求, 最直接的想法, 比较整数大小, 2 > 1永远为true, 反之为false,
但在C#中或C/C++中 2 > 1这样的表达式一样是编译期求值, 所以它们跟 true/false, 0/1 效果一样. 我最先的办法是这样:
if( Math.Max(1, 2) == 2)
稍假思索, 就容易看出这永远是true, 因为涉入了一个BCL中的函数调用, 所以编译器无法知道其返回结果是什么. 不会有编译警告.

类似的方法, if( Math.Max(1, 2) == 1) 来表达false.

然而, 后来我发现了一个狗屎定律, 跟莫菲定律很像: 对程序员, 只要有一个犯错的微弱机会, 他都能捕捉得到这个机会. 也就是说, 上面这样表达式, 有时候你就是会把它整反. 我就整反了, 往往是在简单的bool表达式上, 清醒的时候以为绝不会有如此愚蠢的错误, 偏偏就发生了...

所以经过一点思考之后, 我认为下面这样的C#表达式, 可以把这种犯错的机会减至最小:

if( Math.Max(1,1) == 0)

这个式子在视觉上是一个冲击, 它使得我们不必再定睛看仔细是Max, 还是Min, 3个数, 1和1找出最大, 或最小的, 无论如何不可能出来一个0. 类似地

if( Math.Max(1, 1) == 1)
无论它是其中的哪一个. 都是正确的, 因为被比较的两个数都是1.

这是目前我在C#中的解决方法.

性能?
我根本不关心这事.

现实一点说, Math.Max 这样的函数对你程序的整体性能影响力几乎为0, 除非你在一个循环里做这事无数次. 没有做profile, 我决不自以为是地瞎猜性能瓶颈在哪

回到开始的问题, C/C++中如何做?
我眼前的办法是:
  if(isdigit('1') )
  {
      puts("yes");
  }
表示永远为true

  if(isspace('1') )
  {
      puts("yes");
  }

我有意挑选这两个任何人都不太可能有所犹豫的问题, 1一定是数字, 1一定不是空格, 对isalpha('1') 或 isupper('1') 你未必能说对答案.
阅读(1755) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-25 15:50:58

for(;;) { ... }

chinaunix网友2010-09-25 15:50:58

for(;;) { ... }